moses-palmer/pystray

No icon in system tray

ghanteyyy opened this issue · 4 comments

  • OS : Windows 11
  • Python : 3.9.10

I have the following code which tend to hide the GUI to system tray and works perfectly. But occasionally no icon is found in the system tray like it has never happened.

So, how can I make the following code for hiding GUI in system tray every time ?

from tkinter import *
from pystray import MenuItem as item
import pystray
from PIL import Image, ImageTk


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


def show_window(icon, item):
   icon.stop()
   win.after(0, win.deiconify)


def hide_window():
   win.withdraw()
   image=Image.open("included_files/icon.ico")
   menu=(item('Quit', quit_window), item('Show', show_window))
   icon=pystray.Icon("name", image, "My System Tray Icon", menu)
   icon.run()


win=Tk()
win.title("System Tray Application")
win.geometry("700x350")

win.protocol('WM_DELETE_WINDOW', hide_window)
win.mainloop()

Thank you for your report.

I do not have a definite solution for you, but a simple observation: pystray.Icon.run is blocking, so hide_window will block until pystray.Icon.stop is called.

Have you considered using pystray.Icon.run_detached and modifying pystray.Icon.visible instead of stopping and recreating the icon?

I don't think pystray.Icon.run is blocking hide_window because every time when show_window function gets called; it stops the pystray.Icon.run loop. The script works perfectly but not all the time (for about 7/10 times). And I don't have any idea what's going wrong for that 3 times.

And while using pystray.Icon.run_detached the icon in the system tray won't get destroy.

Occasionally, icon won't show in system-tray when pressed X button but when I start task manager with ctrl+shift+esc then the icon gets shown in system tray.

What is causing this to happen?

I don't think pystray.Icon.run is blocking hide_window because every time when show_window function gets called; it stops the pystray.Icon.run loop. The script works perfectly but not all the time (for about 7/10 times). And I don't have any idea what's going wrong for that 3 times.

pystray.Icon.run is a blocking call and will block the calling thread until the icon is destroyed. This will very likely cause effects such as the one you are observing.

You would call pystray.Icon.run_detached just before win.mainloop(), and ensure that it is not visible. show_window and hide_window would manipulate the visibility of the icon, not destroy and recreate it.

You would call pystray.Icon.run_detached just before win.mainloop(), and ensure that it is not visible. show_window and hide_window would manipulate the visibility of the icon, not destroy and recreate it.

I tried using pystray.Icon.run_detached just before win.mainloop() and also I used icon.visible to show and hide icon instead of recreating every time. But the win.destroy() is not working when I try to quit the program. Why is this happening ?

I changed the above code by the following code as per your instructions

from tkinter import *
from pystray import MenuItem as item
import pystray
from PIL import Image, ImageTk


def quit_window(icon, item):
   icon.visible = False
   icon.stop()
   win.destroy()


def show_window(icon, item):
   icon.visible = False
   win.after(0, win.deiconify)


def hide_window():
   win.withdraw()
   icon.visible = True
   icon.notify('Hello', 'HIDE')


icon_path = 'icon.ico'

win=Tk()
win.title("System Tray Application")
win.geometry("700x350")

image = Image.open(icon_path)
menu = (item('Quit', quit_window), item('Show', show_window))
icon = pystray.Icon("name", image, "My System Tray Icon", menu)

icon.run_detached()
win.protocol('WM_DELETE_WINDOW', hide_window)

win.mainloop()