Icon hang, can't destroy tkinter application
Closed this issue · 1 comments
emcek commented
I have similar short example as some other people. The problem is even I quit application (from system tray icon), root windows is destroy, but icon thread is still running (probably), so whole process hang. I need kill it manually. Do I miss something?
I use partial()
, because GUI is crated in different part of my application and I can not use global state for tk.Tk()
from functools import partial
from pathlib import Path
from pystray import MenuItem, Icon
from PIL import Image
import tkinter as tk
def quit_window(window: tk.Tk, icon: Icon, *args, **kwargs):
print('quit', args, kwargs)
icon.visible = False
icon.stop()
window.destroy()
def show_window(window: tk.Tk, *args, **kwargs):
print('show', args, kwargs)
window.after(0, window.deiconify)
def withdraw_window(window: tk.Tk):
window.withdraw()
def main():
root = tk.Tk()
root.title('DCSpy')
image = Image.open(Path(__file__).resolve().with_name('dcspy.ico'))
menu = (MenuItem('Quit', partial(quit_window, root)), MenuItem('Show', partial(show_window, root)))
icon = Icon('dcspy', image, 'DCSpy', menu)
icon.run_detached()
root.protocol('WM_DELETE_WINDOW', partial(withdraw_window, root))
root.mainloop()
if __name__ == '__main__':
main()
I was thinking, may it is possible to add Event
(from threading
package) to get control over Icon
thread. Then you can event.set()
from outside and thread will be terminated.
emcek commented
solution is replace order of:
root.protocol('WM_DELETE_WINDOW', partial(withdraw_window, root))
icon.run_detached()
and change destroy()
to quit()
def quit_window(window: tk.Tk, icon: Icon, *args, **kwargs):
print('quit', args, kwargs)
icon.visible = False
icon.stop()
window.quit()
Now quit_window()
will close app properly.