結論から言ってしまうとtkinterではなく僕のthreadingの使い方が間違っていました
固まる
tkinterでボタン押下時に固まらないようにthreadingを使ってマルチスレッドにさばくのは有名な話.
以下はボタンを押すとボックスに入力された時間だけ待機し大気中にプログレスバーを動かすプログラム.実行すると関数の処理は走るのだがプログレスバーは動かないしどうにも固まってしまう
import tkinter
from tkinter import ttk
import threading
import time
class Application(tkinter.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.master.geometry("400x400")
self.master.title(u"テスト")
self.create_widgets()
def create_widgets(self):
self.entry = tkinter.Entry(width=7)
self.entry.insert(tkinter.END, '10')
self.entry.place(x=140, y=60)
self.set_button = tkinter.Button(text=u'セット', width=20)
self.set_button.bind("<1>", self.call_func)
self.set_button.place(x=20, y=220)
self.pb = ttk.Progressbar(root, orient="horizontal", length=200, mode="indeterminate")
self.pb.place(x=40, y=280)
def call_func(self, event):
thread1 = threading.Thread(target=self.func(int(self.entry.get())))
thread1.start()
def func(self, t:int):
self.pb.start(10)
time.sleep(t)
self.pb.stop()
if __name__ == "__main__":
root = tkinter.Tk()
app = Application(master=root)
app.mainloop()
解決策
thread1 = threading.Thread(target=self.func(int(self.entry.get())))
どうやら↑これの引数の渡し方が間違いらしい.これでも処理が走ってしまうのでうまくできているように見えるがこれだとメインスレッドで関数が実行されてしまう.
正しい方↓
thread1 = threading.Thread(target=self.func, args=(int(self.entry.get()),))