Samin Jilani
Samin Jilani

Reputation: 155

How to bring back the instance of python tkinter app that is hidden in windows system tray

I have a tkinter app that hides itself in the system tray when closed (X) , and keeps running in the background, I can also bring back the app from hidden tray to the front if I want, and this code works perfectly fine for that. However, there is a complex issue I want to resolve. I want my app to have the same behaviour when it is reopened from outside hidden tray. from shortcut.exe e.t.c. But it opens another instance.

I realized that I only need to do what show_window_action method does normally. But how can I bring that system tray icon back to execute it from newly opened instance?

from PIL import Image, ImageTk
import pystray

    class App:
        def __init__(self):
            self.root = Tk()
            #rest of my code
            ...
    
            self.root.protocol("WM_DELETE_WINDOW", self.hide_window)
        
        def show_window_action(self, icon, item):
            self.system_tray_icon.stop()
            self.root.deiconify()
            image = Image.open("hrm.ico")
            self.menu = (pystray.MenuItem('Quit', self.quit_window), pystray.MenuItem('Show', self.show_window_action))
            self.menu = [item for item in self.menu if item.text != 'Quit']
            self.system_tray_icon = pystray.Icon("name", image, "Edbox Tracker", self.menu)
    
        def hide_window(self):
            image = Image.open("hrm.ico")
            self.system_tray_icon = None
            self.system_tray_icon = pystray.Icon("name", image, "Edbox Tracker", self.menu)
            self.root.withdraw()
            self.system_tray_icon.run()

Upvotes: 2

Views: 78

Answers (1)

acw1668
acw1668

Reputation: 47173

You can create the menu inside __init__() instead of inside show_window_action().

Below is the modified code with missing parts:

from tkinter import *
from PIL import Image
import pystray

class App:
    def __init__(self):
        self.root = Tk()

        # create the icon image and the menu
        self.image = Image.open("hrm.ico")
        self.menu = pystray.Menu(
            pystray.MenuItem('Quit', self.quit_window),
            pystray.MenuItem('Show', self.show_window_action, default=True, visible=False)
        )

        self.root.protocol("WM_DELETE_WINDOW", self.hide_window)

    def mainloop(self):
        self.root.mainloop()

    def quit_window(self):
        self.system_tray_icon.stop()
        self.root.destroy()

    def show_window_action(self, icon, item):
        self.system_tray_icon.stop()
        self.root.deiconify()

    def hide_window(self):
        self.system_tray_icon = pystray.Icon("name", self.image, "Edbox Tracker", self.menu)
        self.root.withdraw()
        self.system_tray_icon.run()

App().mainloop()

Note that I would suggest App inherits from Tk instead of creating the root window inside __init__().

Upvotes: 2

Related Questions