最近、Tkinterをテストして、APIにフックしてそのAPIからデータのサンプルを得ることのできる簡単なアプリケーションを作成し始めました。私が欲しかったことの一つは、このウィンドウを時々リフレッシュして情報を更新して、あまりに古くなったことがないようにすることでした。ウィジェットを再作成するときにTkinterウィンドウがクラッシュする
しかし、tkinterウィンドウが定期的にクラッシュしているようです。エラーやメッセージは返されず、不安定な時間に応答しなくなります。多数のウィジェットを追加すると、クラッシュが早く発生しますが、ウィジェットの数が異なると、最終的に関係なく発生するようです。
間隔を置いて自動リフレッシュさせるために、tkinterアプリケーションのredraw
メソッドを呼び出すスレッドを設定します。私の研究から、tkinterはスレッドセーフではないことが分かっていますが、30秒ごとに1つのスレッドしか実行しないで、実行するのに時間がかかる再描画メソッドを呼び出すと問題にはならないと考えました。
ここでは、いくつかの再描画を試みた後にクラッシュするアプリの最小限のバージョンを紹介します。私の実際のデータには約15のウィジェットとクラッシュしかありませんが、数値を非常に高い値に上げるとクラッシュが早く発生し、テストがより簡単になります。
from Tkinter import *
from threading import Thread, Event
REFRESH_INTERVAL = 30
class App(Frame):
names = ["test"] * 50
def __init__(self, master):
Frame.__init__(self, master)
self.frame = master
self.table = None
self.redraw()
def redraw(self):
if self.table:
self.table.destroy()
new_frame = Frame(self.frame)
new_frame.pack()
self.table = new_frame
for code in self.names:
label = Label(new_frame, text=code)
label.pack()
class Refresher(Thread):
def __init__(self, event, app):
Thread.__init__(self)
self.stopped = event
self.app = app
def run(self):
while not self.stopped.wait(REFRESH_INTERVAL):
print("Refreshing...")
self.app.redraw()
def main():
root = Tk()
app = App(root)
app.pack(side=TOP, fill="both", expand=True)
stop_flag = Event()
refresher = Refresher(stop_flag, app)
refresher.start()
root.mainloop()
stop_flag.set()
if __name__ == "__main__":
main()
tkinterはスレッドではうまく機能しません。ルートウィンドウを作成したスレッド以外のスレッドからtkinter関数やウィジェットメソッドを呼び出すべきではありません。簡単なタイマーのためだけにスレッドは必要ありません。 'after'メソッドを読んでください。 –
@BryanOakleyああ、 'after'メソッドは私のために働いているように見え、今それをテストしています。それを回答として投稿したいですか? – SuperBiasedMan