環境:
Ubuntu 18.04.5 LTS (Windows Subsystem for Linux)
Python 3.8.0
VcXsrv 1.20.5.1
目標
PythonのTkinterでチェックボックス(Checkbutton)にチェックをつけると、入力欄(Entry)が有効になり入力できるようにする。
チェックを外すと、編集できなくする。
方法
import tkinter as tk
def change_state():
if bool_check.get():
# チェックをつけたとき
entry.config(state='normal')
else:
# チェックをはずしたとき
entry.config(state='disabled')
root = tk.Tk()
entry = tk.Entry()
entry.config(state='disabled') # 最初は無効
bool_check = tk.BooleanVar()
bool_check.set(False) # 最初はチェックなし
check = tk.Checkbutton(variable=bool_check, command=change_state)
check.pack()
entry.pack()
root.mainloop()
change_state関数を定義します。
変数名は何でもいいですが、例えばbool_check変数にtk.BooleanVar()を代入します。
tk.Checkbutton()の引数variableにbool_check変数を、引数commandにchange_state関数を渡してチェックボックスを作成します。
チェックの有無はbool_check.get()でブール値で返されます。
チェックをつけはずしするとchange_state()が呼ばれます。
change_state()では作製したentryのstateをチェックの有無に応じて変更します。
2つ以上作りたいとき
change_state()にbool_checkやentryを引数として渡せられれば、2つ以上の入力欄で同様のことができそうです。
しかしながら例えば、
def change_state(bool_check, entry):
if bool_check.get():
entry.config(state='normal')
else:
entry.config(state='disabled')
のようにchange_state関数を引数付きで定義して、
tk.Checkbutton(command=change_state(bool_check, entry))
のようにtk.Checkbutton()のcommand引数に、引数付きの関数を渡しても正しく動作しません。
正しく動作するには、commandにlambda式を渡します。すなわち、
import tkinter as tk
def change_state(bool_check, entry):
if bool_check.get():
entry.config(state='normal')
else:
entry.config(state='disabled')
root = tk.Tk()
# 1つ目
entry1 = tk.Entry()
entry1.config(state='disabled')
bool_check1 = tk.BooleanVar()
bool_check1.set(False)
check1 = tk.Checkbutton(text='1', variable=bool_check1,
command=lambda: change_state(bool_check1, entry1))
check1.pack()
entry1.pack()
# 2つ目
entry2 = tk.Entry()
entry2.config(state='disabled')
bool_check2 = tk.BooleanVar()
bool_check2.set(False)
check2 = tk.Checkbutton(text='2', variable=bool_check2,
command=lambda: change_state(bool_check2, entry2))
check2.pack()
entry2.pack()
root.mainloop()
こちらの書き方の方が、change_state関数がグローバル変数に依存せず良いような気がします。
簡単な応用
チェックをはずすと、入力されていた文字列を削除して"無効"を表示してみる。
import tkinter as tk
def change_state():
if bool_check.get():
# チェックをつけたとき
entry.config(state='normal')
entry.delete(0, tk.END) # normalにしてから"無効"をdeleteする
else:
# チェックをはずしたとき
entry.delete(0, tk.END) # 0文字目から終わりまで文字列を削除する
entry.insert(0, "無効") # Entryの0文字目に"無効"をinsert
entry.config(state='disabled') # insertしてからdisableにする
root = tk.Tk()
entry = tk.Entry()
entry.insert(0, "無効") # Entryの0文字目に"無効"をinsert
entry.config(state='disabled') # insertしてからdisableにする
bool_check = tk.BooleanVar()
bool_check.set(False)
check = tk.Checkbutton(variable=bool_check, command=change_state)
check.pack()
entry.pack()
root.mainloop()
初期値を与えるなど、応用ができそうです。