同时使用Tkinter与Pystray时窗口无法退出的问题求助
Tkinter + Pystray 托盘退出无法关闭窗口的解决办法
点击系统托盘的Quit选项时,只有icon.stop()生效,window.quit()和window.destroy()无法关闭Tkinter窗口,核心原因是:pystray的run_detached()会在独立线程中运行托盘逻辑,而Tkinter要求所有GUI操作必须在主线程(即运行mainloop()的线程)执行,跨线程直接调用窗口操作会导致失效。
解决思路
通过Tkinter的after()方法,把窗口关闭操作提交到主事件循环中执行,确保操作在主线程完成。
修改后的完整代码
from pystray import MenuItem as item import pystray from PIL import Image import tkinter as tk window = tk.Tk() def quit_window(icon, item): # 先停止并隐藏托盘图标 icon.visible = False icon.stop() # 将窗口销毁操作提交到Tkinter主事件循环 window.after(0, lambda: window.destroy()) def show_window(icon, item): window.after(0, window.deiconify) def withdraw_window(): window.withdraw() window.title("Welcome") win_width = window.winfo_screenwidth() win_height = window.winfo_screenheight() app_width = 200 app_height = 200 center_width = (win_width / 2) - (app_width / 2 ) center_height = (win_height / 2 ) - (app_height / 2) print("모니터 사이즈 : ",win_width, win_height) print("모니터 중심점 : ", int(center_height), int(center_width)) window.resizable(False, False) window.geometry(f"{app_width}x{app_height}+{int(center_width)}+{int(center_height)}") window.config(highlightbackground='black') label = tk.Label(window,bd=0,bg='black') window.overrideredirect(True) window.wm_attributes('-transparentcolor','black') canvas= tk.Canvas(window, width=win_width, height=win_height, bg = 'black') image = Image.open("icon.jpg") menu = (item('Quit', quit_window), item('Show', show_window)) icon = pystray.Icon("name", image, "title", menu) icon.run_detached() window.protocol('WM_DELETE_WINDOW', withdraw_window) window.mainloop()
关键修改点
- 用
window.after(0, lambda: window.destroy())替代直接调用窗口关闭方法:after(0)会将传入的函数放到Tkinter主事件循环的下一轮执行队列,保证操作在主线程运行。 - 先执行
icon.stop()停止托盘线程,再触发窗口销毁,避免线程间的资源冲突。
内容的提问来源于stack exchange,提问作者Raen Lusa lat
相关产品推荐
相关产品推荐

