tk在子线程中关闭报错 async handler deleted by the wrong thread
时间: 2024-06-11 10:07:29 浏览: 235
【面试】可以在子线程直接new一个Handler吗?怎么做?
这个报错通常是因为在子线程中尝试关闭`tkinter`的窗口或者更新`tkinter`的控件,而`tkinter`的操作必须在主线程中执行。
解决方法是,在子线程中不直接操作`tkinter`控件,而是通过`Queue`将操作请求发送到主线程,由主线程执行相应的操作。具体实现可以参考以下代码:
```python
import tkinter as tk
import threading
import queue
class App:
def __init__(self):
self.root = tk.Tk()
self.label = tk.Label(self.root, text='Hello World')
self.label.pack()
self.queue = queue.Queue()
def run(self):
threading.Thread(target=self.worker).start()
self.root.mainloop()
def worker(self):
while True:
try:
cmd, args = self.queue.get(timeout=0.1)
if cmd == 'update_label':
self.update_label(*args)
elif cmd == 'close_window':
self.close_window()
return
except queue.Empty:
pass
def update_label(self, text):
self.label.config(text=text)
def close_window(self):
self.root.destroy()
def on_button_click(self):
self.queue.put(('update_label', ('New Text',)))
def on_close(self):
self.queue.put(('close_window', ()))
if __name__ == '__main__':
app = App()
button = tk.Button(app.root, text='Update Label', command=app.on_button_click)
button.pack()
app.root.protocol('WM_DELETE_WINDOW', app.on_close)
app.run()
```
在上面的代码中,`App`类中增加了一个`queue`属性,用于存放需要在主线程中执行的操作请求。`update_label`和`close_window`方法分别表示更新`Label`控件和关闭窗口的操作,将对应的操作请求通过`queue`发送到主线程中执行。`worker`方法在子线程中运行,循环从`queue`中获取操作请求,根据请求类型执行相应的操作。`on_button_click`和`on_close`方法表示按钮点击和窗口关闭事件的回调函数,在这些方法中将需要执行的操作请求放入`queue`中。最后,在`run`方法中启动子线程,并在主线程中运行`mainloop`循环,等待操作请求的执行。
这样,就可以在子线程中调用`update_label`和`close_window`方法,而不会出现`async handler deleted by the wrong thread`的错误。
阅读全文