Tkinterにおけるタイマー処理、ボタン処理

プログラミング

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というものでしょう。

中身はともかく、これでプログラムは書けそう。

コメント