TkinterでCheckbuttonにチェックを付けると、Entryが編集できるようにする


環境:
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()

初期値を与えるなど、応用ができそうです。