moses-palmer / pystray

GNU General Public License v3.0
461 stars 57 forks source link

pystray doesn't show window again #124

Closed danilobatistaqueiroz closed 2 years ago

danilobatistaqueiroz commented 2 years ago

If I close the window and show it using the menu, everything works fine. But if I close again and try to show it than, it won't work. The event isn't even fired. I'm using Ubuntu with Cinnamon.

I noticed that the icon and menu are recreated.
I adapted a version using icon and menu globals, to avoid recreating, but it didn't work. It seems a problem in _base.py in stop() method, where self._running = False

It seems that stop() method doesn't kill the thread for icon in linux.

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk

window = tk.Tk()
window.title("Welcome")

def quit_window(icon, item):
    icon.stop()
    window.destroy()

def show_window(icon, item):
    print('show')
    icon.stop()
    window.after(0,window.deiconify)

def withdraw_window():  
    print('withdraw')
    window.withdraw()
    image = Image.open("alarm4.ico")
    menu = (item('Quit', quit_window), item('Show', show_window))
    icon = pystray.Icon("name", image, "title", menu)
    icon.run()

window.protocol('WM_DELETE_WINDOW', withdraw_window)
window.mainloop()
ppizarror commented 2 years ago

What happens if you run with icon.run_detached()?

moses-palmer commented 2 years ago

Thank you for your report.

I have tested your sample application, and it appears to work as you expect it to. I am, however, using the AppIndicator backend.

The most troublesome part of your code, I think, is the call to icon.run() in withdraw_window; this method will block until the icon is destroyed, and UI-toolkits such as TKinter usually do not like it when you block the main method.

run_detached, as suggested above, probably will not work either, as it requires that the framework you are integrating with uses the same kind of mainloop as this library, and I presume TKinter uses an X mainloop, whereas the usable backends for this library use GTK.

If you do not target macOS, my suggestion would be to run the icon in a separate thread, and let show_window and withdraw_window manipulate the visibility of the icon instead.