Python/tkinter 複数チェックボックス(Checkbutton)の制御

Python複数チェックボックス制御
  • URLをコピーしました!
※当ブログではアフィリエイト広告を表示しています

Python初心者がブログの検索順位取得ツールを作っています。

今まで、キーワードを検索してファイルに書き出す部分、ちょっとしたGUIの作成等を行ってきました。

今回は、画面に表示された表のチェックボックス(Checkbutton)の制御部分を作成していきます。

  • 複数行にわたって配置されたチェックボックスが個々に動作すること
  • 全部一括選択/全部一括解除ができること
  • チェックされた行のキーワードを取得できること

を目標にしていきます。

現状の画面は以下のとおり。

前回はキーワードやタイトルをソースに埋め込んでいましたが、Excelファイルを読み込めるように改良しました。

また、必要なボタンも追加し、画面案に近い画面が出せるようになっています。

検索順位Excelファイルを読み込ませた画面
作りたい画面
当初の画面案
目次

複数チェックボックスを制御するソースコード

Python/tkinterで複数のチェックボックス(Checkbutton)の動作を作りこんでみました。

チェックボックス(Checkbutton)に関連する箇所のみ載せます。

ちなみに、ソースの行が多くなってきたので、今回から関数化させてみました。

import os
import sys
import tkinter
from tkinter import messagebox
from tkinter import filedialog
import tkinter.ttk

rt_width=600
rt_hgt=300

#selctボタンを押したときの処理
def select_click():
	
	fileType = [('Excelファイル','*.xlsx')] #ファイルタイプをExcelファイルに指定
	iniDir = os.path.abspath(os.path.dirname(__file__)) #初期表示フォルダ
	global filepath	
	filepath = filedialog.askopenfilename(filetypes=fileType,initialdir = iniDir)
	
	if len(filepath) < 1:
		print('exit ブログ検索順位取得ツール')
		sys.exit()

	#Excel読み込み 戻り値はリストを3つ返す
	global list_keyword
	global list_rank
	global list_title
	list_keyword,list_rank,list_title=readExcelFile() #関数の中身は省略
	makeList()

#表を作成
def makeList():

	global list_keyword #検索キーワード一覧
	global list_rank    #順位一覧
	global list_title   #記事タイトル一覧

	num_list = len(list_keyword) #リストの数
	
	if 'rank_str_list' in globals():    #update or 画面サイズ変更
		print('rank update')
	else:
		global rank_str_list
		rank_str_list = list_rank     #ファイル読み込み時の表示

	#Canvas widgetを生成
	cv_width=rt_width-20
	cv_hgt=rt_hgt-70
	canvas = tkinter.Canvas(root,width=cv_width,height=cv_hgt,bg='white') #背景を白に
	canvas.grid(row=1,rowspan=num_list,column=0,columnspan=5)     #5列分

	#スクロールバー
	vbar=tkinter.ttk.Scrollbar(root,orient=tkinter.VERTICAL) #縦方向
	vbar.grid(row=1,rowspan=25,column=5,sticky='ns') 

	#スクロールバーの制御をCanvasに通知する処理
	vbar.config(command=canvas.yview)

	#Canvasの可動域をスクロールバーに通知する処理
	canvas.config(yscrollcommand=vbar.set)

	#スクロール可動域<=これがないと、どこまでもスクロールされてしまう。
	sc_hgt=25*(num_list+1)
	print(str(sc_hgt))
	canvas.config(scrollregion=(0,0,cv_width,sc_hgt))

	#Frameを作成
	frame = tkinter.Frame(canvas,bg='white') #背景を白に

	#frameをcanvasに配置 
    canvas.create_window((0,0),window=frame,anchor=tkinter.NW,width=canvas.cget('width'))   #anchor<=NWで左上に寄せる
	
	#各ラベルの幅(文字がある場合は文字ユニットとなる)
	c0_width=5  #チェックボックス
	c1_width=25 #検索キーワード
	c2_width=10  #順位
	c3_width=70 #記事タイトル

	#header row=1に設定する文字列 余白は0に
	e0=tkinter.Label(frame,width=c0_width,text='select',background='white')
	e0.grid(row=1,column=0,padx=0,pady=0,ipadx=0,ipady=0) #0列目

	e1=tkinter.Label(frame,width=c1_width,text='keyword',background='white',anchor='w')
	e1.grid(row=1,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目

	e2=tkinter.Label(frame,width=c2_width,text='rank',background='white',anchor='w')
	e2.grid(row=1,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目
	
	e3=tkinter.Label(frame,width=c3_width,text='title',background='white',anchor='w')
	e3.grid(row=1,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目 
	
	irow = 2
	irow0=2
	erow=num_list+irow0
	
	global list_chk	
	list_chk = []

	while irow < erow:   #リストの数分ループしてLabelとチェックボックスを設置
		#色の設定
		if irow%2==0:
			color='#cdfff7'  #薄い青
		else:
			color='white'
		
		#チェックボックスの設置
		bln=tkinter.BooleanVar()		
		bln.set(False) 
		c = tkinter.Checkbutton(frame,variable = bln,width=c0_width,text='',background='white')
		list_chk.append(bln) #チェックボックスの初期値
		c.grid(row=irow,column=0,padx=0,pady=0,ipadx=0,ipady=0)  #0列目
		#検索キーワード
		a1=list_keyword[irow-irow0]
		b1=tkinter.Label(frame,width=c1_width,text=a1,background=color,anchor='w')
		b1.grid(row=irow,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目
		#検索順位
		a2=rank_str_list[irow-irow0]
		if ('↑' in str(a2)) == True:
			a2color = 'red'
		elif ('↓' in str(a2)) == True:
			a2color = 'blue'
		else:
			a2color = 'black'
		b2=tkinter.Label(frame,width=c2_width,text=a2,foreground=a2color,background=color,anchor='w')
		b2.grid(row=irow,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目
		#記事タイトル
		a3=list_title[irow-irow0]
		b3=tkinter.Label(frame,width=c3_width,text=a3,background=color,anchor='w')
		b3.grid(row=irow,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目
		
		irow=irow+1
	
	#リストの下に設置するボタン
	allSelectButton = tkinter.Button(root,text='全て選択',command=allSelect_click)
	allSelectButton.grid(row=erow,column=0)  #1列目
	allClearButton = tkinter.Button(root, text='選択解除',command=allClear_click)
	allClearButton.grid(row=erow, column=1)   #1列目
	plotButton = tkinter.Button(root, text='make plot',command=make_plot)
	plotButton.grid(row=erow,column=3)   #3列目

#全て選択をチクリック
def allSelect_click():
	for i in range(len(list_chk)):
		list_chk[i].set(True)

#選択解除をクリック
def allClear_click():
	for i in range(len(list_chk)):
		list_chk[i].set(False)

#プロット作成ボタンをクリック(現状はチェックの状態を調べるのみ)
def make_plot():
	global list_keyword
	global list_chk
	
	print('make_plot')
	
	num_list = len(list_keyword)
	
	list_plot_keyword = []
	
	for ilist in range(num_list):
		bln = list_chk[ilist].get()   #checkbuttonの値
		if bln == True:  #チェック済みの行
			list_plot_keyword.append(list_keyword[ilist])	
	print(list_plot_keyword)

#メイン関数
def main():
	
	global root
	root = tkinter.Tk()
	root.title('ブログ検索順位取得ツール') #タイトル

	root.geometry(str(rt_width)+'x'+str(rt_hgt)) #サイズ

	#ファイル選択ボタンを作成(コマンド関数は省略)
	selectButton = tkinter.Button(root, text='File Select',command=select_click)
	selectButton.grid(row=0,column=1)
	#順位アップデートボタン(コマンド関数は省略)
	updateButton = tkinter.Button(root, text='Update Rank',command=update_click)
	updateButton.grid(row=0,column=2)
		
	#ウィンドウを動かす
	root.mainloop()

if __name__ == '__main__':
	main()

今回の重要箇所は、106行目からのチェックボックスの配置の部分、141行目からの全選択/全解除ボタンの動作、あとは161行目からのチェックされている行の取得する部分です。

108行目のCheckbuttonの宣言で「variable=」と指定してあげるのがポイント。variableで指定した変数にチェックボックスの値 (True/False) が格納されます。

そして「list_chk」というリストに各チェックボックスの値を保持するようにしました。

チェックボックスの値を設定するには「set(True/False)」(143,148行目)を、チェックボックスの値を取得するには「get()」(162行目)を使用します。

画面下部に配置した「全て選択」ボタンをクリックすると、全ての行のチェックボックスがチェックされます。
「選択解除」ボタンをクリックすると、チェックされている行のチェックボックスが全てチェックを外されるようになっています。

実行結果

上記で作成したコードを動かしてみました。

今回はScreenToGifというツールを使って、動画を操作している動画を撮ってみました。

複数のチェックボックスの動作確認しているGIF動画
チェックボックスの動作確認結果

やりたいこと

  • 「全て選択」ボタンで全部のチェックボックスをチェック
  • 「選択解除」ボタンで全部のチェックを外す
  • チェックボックスを個別にチェックできる(連動していない)

ができています。

また、動画には出していませんが、「make plot」ボタンを押すとコマンド画面にチェックされた行のキーワード一覧が表示されるようになっています。

注意点

複数あるチェックボックスを制御するうえで躓いたところがあります。

最初、チェックボックス設置の部分で、チェックボックスの初期値をループの外で設定していました。

そうすると全てのチェックボックスが連動してしまい、1つチェックを入れると全てチェックされてしまうようになってしまいました。

チェックボックスが連動してしまっている動画
チェックボックスが連動してしまっている

そのときのコード(抜粋)がこちら。

bln=tkinter.BooleanVar()		
bln.set(False) 
while irow < erow:   #リストの数分ループしてLabelとチェックボックスを設置
		
    #チェックボックスの設置
	c = tkinter.Checkbutton(frame,variable =bln,width=c0_width,text='',background='white')
	list_chk.append(bln) #チェックボックスの初期値

1,2行目の初期値(bln)の設定をwhile文の中に入れたら、チェックボックスが個別に動作するようになりました。

初期値は全部Falseなんだから、1回宣言すればいいじゃん、と思っていたのですが、そうではないようです。


こんなわけで、だいぶGUIもツールとして様になってきました。

あとはチェックされた行のデータでプロットを作成する機能が必要なので、そこを作っていきます。

んじゃ、また~

おススメのプログラミング独学方法はこちらの記事にまとめました!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

関連記事

応援よろしくお願いします☆

この記事を書いた人

理系夫婦の妻のほうです。
大学、大学院(修士)で物理を専攻。
2016年に長女を出産、2021年に長男を出産。
フルタイム勤務ワーママ→休職→専業主婦。

コメント

コメントする

目次