Question

There actually is no problem with my code per se, but if I add my program to run on startup (i.e. every time the user logs in), it fails to create the tray icon, because, at the time it tries to, the taskbar is not yet created/initialized completely. Is there a solution for that? Right now I'm thinking about something like retrying 10 times with a 10 second interval.

Was it helpful?

Solution

It certainly is a race condition. Retrying is a good idea, yes, but instead I'd do it with delays. Have the app launch but use a QTimer::singleShot() to delay for 5 seconds (or whatever) before trying to hookup with the taskbar. If you want to retry after that (which is probably a good idea), delay longer (as retrying immediately likely won't succeed either as the retry will occur too fast).

OTHER TIPS

Quote from http://developer.qt.nokia.com/doc/qt-4.8/qsystemtrayicon.html (pay attention to second paragraph):

"To check whether a system tray is present on the user's desktop, call the QSystemTrayIcon::isSystemTrayAvailable() static function." ...

"If the system tray is unavailable when a system tray icon is constructed, but becomes available later, QSystemTrayIcon will automatically add an entry for the application in the system tray if the icon is visible."

Moca is right, it should work as per the docs. However, it does not due to bug 61898 in Qt.

A workaround is to wait for the system tray to be available using isSystemTrayAvailable(). As Wes Hardaker suggests, you can try every few seconds using a QTimer::singleShot() until the system tray is available.

Note that if you show() your tray icon once the system tray is available, it will always show up again even if the system tray is removed and a new one is created (as the docs says), so you only need to get it right the first time.

I'm using PyQt5, and I replaced

self.show()

with

self._show_when_systray_available()

def _show_when_systray_available(self):
    """Show status icon when system tray is available 

    If available, show icon, otherwise, set a timer to check back later.
    This is a workaround for https://bugreports.qt.io/browse/QTBUG-61898
    """
    if self.isSystemTrayAvailable():
        self.show()
    else:
        QtCore.QTimer.singleShot(1000, self._show_when_systray_available)

I can only see one (pretty unlikely) failing case: a race condition where the system tray is removed in the small amount of time after isSystemTrayAvailable() returns true and before your status icon shows.

Edit: Accorging to the bugtracker, this was fixed in 5.12.4.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top