Python Forum
[PyQt] Priority problem with PyQt5 QMenu() and QSystemTrayIcon() - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [PyQt] Priority problem with PyQt5 QMenu() and QSystemTrayIcon() (/thread-3466.html)



Priority problem with PyQt5 QMenu() and QSystemTrayIcon() - Alfalfa - May-25-2017

I made a very simplistic GUI which rely mainly on the status of the system tray icon. Overall it works fine, but there seems to be a problem with the execution of Qt's setIcon() function from QMenu(). When setIcon() is called from anywhere, it works as expected. However, when is it called from a QMenu action, the function is queued and executed only AFTER it's parent function is done. As an example, here is a very stripped code where QMenu use the function test() to change the system tray icon.

When test() is fired, it waits until time.sleep() (or the usual load) is done to change the icon. Therefore, you see "test function start", wait 3s, "test function end" and finally the icon is changed. Among others things, I tried passing QtCore.Qt.DirectConnection in connect(), but nothing worked so far. Does anyone have an idea of how I can solve this? Thanks!

#!/usr/bin/python3
import sys
import time
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSystemTrayIcon

class syncWorker(QObject):
   setIcon = pyqtSignal(str)

   def __init__(self):
       super().__init__()

   @pyqtSlot()
   def loop(self):
       while True:
           self.setIcon.emit("icon1")
           time.sleep(10)

class initGui(QtWidgets.QMainWindow):
   def __init__(self):
       super().__init__()

       menu = QtWidgets.QMenu()
       menu.addAction('Show icon 2', self.test)
       menu.addAction('&Quit', app.exit)
       self.trayIcon = QSystemTrayIcon()
       self.trayIcon.setContextMenu(menu)

       self.worker = syncWorker()
       self.workerThread = QThread() #move the Worker object to the Thread object
       self.workerThread.started.connect(self.worker.loop) #init worker loop
       self.worker.moveToThread(self.workerThread)
       self.worker.setIcon.connect(self.setIcon)
       self.workerThread.start()
       self.trayIcon.show()

   def test(self):
       print("test function START")
       #
       self.setIcon("icon2")
       time.sleep(3)
       #
       print("test function END")

   def setIcon(self, name):
       icon = QtGui.QIcon(name + '.svg')
       self.trayIcon.setIcon(icon)

if __name__== '__main__':
   app = QtWidgets.QApplication(sys.argv)
   Dialog = initGui()
   sys.exit(app.exec_())



RE: Priority problem with PyQt5 QMenu() and QSystemTrayIcon() - Alfalfa - May-31-2017

In case anyone wonder, the real code is available on GitHub.