我的代码如下所示:
from tkinter import *
from threading import Timer
root = Tk()
###
def print_data():
Timer(1.0, lambda: print_data()).start()
data.set('sdsds')
###
data = StringVar()
data_label = Label(root, bg = '#FFF', textvariable = data)
data_label.pack()
timer = Timer(1.0, lambda: print_data());timer.start()
root.mainloop()
这将引发RuntimeError: main thread is not in main loop
。
我尝试过的:
root.protocol("WM_DELETE_WINDOW", lambda: timer.cancel()) (close button will not work)
怎么了?
tkinter
不支持多线程,因为一个多线程应用程序中只有一个线程可以使用它。当mainloop()
在主线程中运行时,计时器线程会打破该规则并尝试更改名为data
的StringVar
的值。
我不理解您的代码试图实现的一切,但下面展示了如何做一些非常类似的事情,并通过每隔500毫秒定期轮询一个全局标志来避免RuntimeError
,以查看print_data()
函数是否已经运行。
import tkinter as tk # PEP 8 preferred style.
from threading import Timer
def print_data():
global printed
global timer
printed = True
timer = Timer(1.0, print_data)
timer.start()
def check_printed():
global printed
if printed:
data.set('sdsds')
printed = False
root.after(500, check_printed) # Check again in 500 ms.
root = tk.Tk()
data = tk.StringVar()
data_label = tk.Label(root, bg='#FFF', textvariable=data)
data_label.pack()
timer = Timer(1.0, print_data)
timer.start()
printed = False
check_printed() # Start polling flag.
def shutdown():
"""Orderly app shutdown."""
if timer.is_alive():
timer.cancel()
root.destroy()
root.protocol("WM_DELETE_WINDOW", shutdown)
root.mainloop()
print('fini')