PythonでGUIを構築していると、例によってスレッドの問題が気になる。
tkinterで最小限のコードといえば、こうなるのではないだろうか?
from tkinter import *
window = tk()
window.mainloop()
exit()
ここでwindow.mainloop()のあと、処理は戻ってこない。
tkinter側の処理を終わらない限り。
当たり前だけれど、シングルスレッドということだ。
しかし、tkinterはよくできていて非同期な動作をカバーしている。
典型的なものが、タイマーとボタンを押した時のイベント処理。
それを調べるために、こんなプログラムを書いた。
from tkinter import *
command_id = 0
def timer():
global command_id
time = int(buff.get())
if time > 0:
command_id = frame.after(1000, timer)
time -= 1
buff.set(str(time))
else:
frame.after_cancel(command_id)
buff.set("10")
def push():
val = int(btnval.get())
val+=1
btnval.set(str(val))
#----------------------------
frame = Tk()
buff = StringVar()
buff.set('10')
entry = Entry(frame, textvariable = buff)
entry.grid(row=0,column=0)
button = Button(frame, text = 'START', command = timer)
button.grid(row=0,column=1)
btnval = StringVar()
btnval.set('0')
label = Label(frame, textvariable=btnval)
label.grid(row=1,column=0)
btn2 = Button(frame, text='Push',command=push)
btn2.grid(row=1,column=1)
frame.mainloop()
print("END")
タイマーはtimer中でframe.after(秒数、コマンド)で処理される。
このframe.afterは「固有ID」というものを返すそうだ。
なので、勉強のためにタイマーがマイナスになったらframe.after_cancel(固有ID)で終了させてみた。
本当は別のトリガーでタイマーをキャンセルしたくなった時に使うものだろう。
このタイマー処理をしている最中でも、pushボタンを押すと反応する(数字が増える)
最後の行にprint(“END”)を入れているが、GUIを終了しないと、コンソールにENDは出ない。
それがGUIというものでしょう。
中身はともかく、これでプログラムは書けそう。