Search code examples
pythonmultithreadingpython-3.xsystem-tray

Systray blocking further Execution of Code


I found SysTrayIcon.py to easily create a Systray Icon in Windows. Problem is, it is blocking the further Execution of Code, as an example, this is how i create my current trayicon:

import _tray #This is a simple import of SysTrayIcon.py

#Create SysTray
def EXIT(self): None
def DEBUG(self): print("TEST")
def SHOW(self): print("Showing Main Window")
HOVER = "Foo v"+version
ICON = root+"apr.ico"
MENUE =(('1', None, DEBUG),
        ('2', None, SHOW),
        ('Sub', None, (
            ('Sub 1', None, DEBUG),
            ('Sub 2', None, DEBUG),)))

_tray.SysTrayIcon(ICON, HOVER, MENUE, on_quit=EXIT, default_menu_index=1)

if i now add lets say this code:

print("This get's executed after the Trayicon is quit.")

to the other Code it doesn't get executed until i Quit the Trayicon, how can i avoid/fix said behaviour?


Solution

  • You can use threads to separate the WIN32 API context hold from your app logic. For example, if you replace the direct call with:

    import threading
    
    def run_systray(icon, hover, menu, **options):
        _tray.SysTrayIcon(icon, hover, menu, **options)
    
    thread = threading.Thread(target=run_systray,
                              args=(ICON, HOVER, MENUE),
                              kwargs={"on_quit": EXIT, "default_menu_index": 1})
    thread.start()
    
    print("This gets executed immediately...")
    
    # you can do whatever you want here
    
    # in the end, lets cleanly handle the thread closing:
    thread.join()
    
    print("This gets executed only after systray exit...")
    

    the SysTrayIcon class will happily chat with WIN32 API without blocking the rest of the code until you decide to join the thread back to the main one.