Python Forum
[PyQt] Priority problem with PyQt5 QMenu() and QSystemTrayIcon()
Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] Priority problem with PyQt5 QMenu() and QSystemTrayIcon()
#1
Bug 
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_())
Reply
#2
In case anyone wonder, the real code is available on GitHub.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Which GUI toolkit to use if less resource consumption is a priority. NIHILIST 1 2,323 Aug-28-2020, 08:03 PM
Last Post: jefsummers
  [PyQt] Hide Dock Icon for QSystemTrayIcon App AeglosGreeenleaf 0 3,264 Jun-20-2019, 07:21 PM
Last Post: AeglosGreeenleaf
  Huge code problems (buttons(PyQt5),PyQt5 Threads, Windows etc) ZenWoR 0 2,785 Apr-06-2019, 11:15 PM
Last Post: ZenWoR
  QMenu tearoff and questions kiteh 0 2,620 Jan-21-2019, 05:44 PM
Last Post: kiteh
  PyQt5 undefined symbol problem ujjwalrathod007 3 2,822 Aug-18-2018, 10:26 AM
Last Post: Axel_Erfurt

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020