I am trying to print a text when system tray icon is clicked in PyQT5 program. I tried to connect PyQT5 QSystemTrayIcon activated signal (emitted when system tray icon is clicked) to custom method, but the method is not called. Here is simple example:
import sys
from PyQt5.QtWidgets import QSystemTrayIcon, QApplication
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
@pyqtSlot()
def action(signal):
print('test1')
app = QApplication(sys.argv)
icon = QSystemTrayIcon(QIcon('any_icon.png'), app)
icon.show()
icon.activated.connect(action)
#icon.activated['QSystemTrayIcon::ActivationReason'].connect(action)
#icon.pyqtConfigure(activated=action)
print(icon.receivers(icon.activated)) # to check if is connected
sys.exit(app.exec_())
In example are 3 ways of connecting the signal to slot (two of them commented). I tried both using method with and without decorator @pyqtSlot(). Connection raises no errors. Even the print of signal receivers says it is connected to 1 slot. However, it does nothing when systray icon is clicked.
The question: Is the signal connection incorrect, or is the signal not emitted at all?
System: Ubuntu 16.04, PyQT5.8. However, should be working on others systems too as PyQT is multiplatform-ish. PS: I have read official PyQT5 signal/slot documentation and many related questions on stack overflow, but had not found the same issue. The closest one I think may relate is in C++, but not applicable to python. Any tips would be really appreciated. Thank you very much! Edit: fixed typos in text
Based on @Murdo and @eyllanesc answers, I tested the sample code on multiple systems.
Clean install only with Python 3.5 and pip3 install pyqt5
. System tray icon activated signal is:
Not working:
Working:
It seems like the sample code is correct and there is a bug in QT using Unity - QSystemTrayIcon
does not send activated
signal when the system tray icon is clicked. Bug report link.
SOLUTION QSystemTrayIcon
activation (clicked) signal can be bypassed by assigning a QMenu
to the system tray icon and detecting QMenu().aboutToShow
signal instead. This way when the tray icon is clicked, signal aboutToShow
is sent, then menu displayed. It is not exactly the same result, but there seems to be no other way of detecting system tray icon activation on Unity. Thanks to @Murdo for an idea. Simple code example:
import sys
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu
from PyQt5.QtGui import QIcon
def action():
print('System tray icon clicked.')
app = QApplication(sys.argv)
icon = QSystemTrayIcon(QIcon('any_icon.png'), parent=app)
icon.show()
menu = QMenu(parent=None)
menu.aboutToShow.connect(action)
icon.setContextMenu(menu)
sys.exit(app.exec_())