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
Your example works just fine in Xubuntu under openbox with stalonetray.
However in Xubuntu proper it did not work !
But when I added something like:
mNu = QMenu()
test = QAction('Test',mNu)
test.triggered.connect(action)
icon.setContextMenu(mNu)
it worked in xubuntu. I seems that somehow Ubuntu only expects to show a menu in the tray thing.
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:
Ubuntu 16.04 - Unity, PyQt 5.8 and PyQt 5.5.1
Ubuntu 16.10 - Unity, PyQt 5.8 and PyQt 5.7
Working:
Ubuntu 16.04 - Gnome, PyQt 5.8
Arch Linux - Gnome, PyQt 5.8
Kubuntu 16.10, KDE, PyQt 5.7
Xubuntu - Openbox with Stalonetray
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_())
Related
I've now swapped over to Pycharm and PyQt5 as it had better support an integration.
Our school has just upgraded to M1 chips and now my solution doesn't work.
I can download the latest version of python 3.10.2.
I then run the following command in terminal.
Python3.10.2 -m pip install PyQt6
To test the code I then type this into idle:
import sys
from PyQt6 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
widget.resize(400, 200)
widget.setWindowTitle("This is PyQt Widget example")
widget.show()
exit(app.exec())
This all works perfectly and a window will be displayed.
I then open up Pycharm 2021.3 community edition.
Select the same interpreter and load global dependencies.
I run it and then this is the error I get
From what I can read PyQt6 supports both the Arm and 86 architecture from the same download source. Is it possible to force an interpreter to use just the arm or does PyCharm know to do this intuitively?
I'm trying to get students to use the drop and drag builder with QT designer first.
I have been using the QT designer tool which saves GUIs as a XML template. PySide2 is able to covert this to a Python Class file.
Utilizing the tool for an XML that includes QWebEngineView
pyside2-uic GUI_NEW.ui > ui_main.py
The first few lines of the ui_main.py call for
################################################################################
## Created by: Qt User Interface Compiler version 5.15.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from QWebEngineView import QWebEngineView
running the file that utilizes this, results in:
ModuleNotFoundError: No module named 'QWebEngineView'
So far I have tried
Trying PySide6 over PySide 2
Replaced the import line with
from PySide2.QtWebEngineWidgets import QWebEngineView
The Application runs but completely hangs
pip install PyQtWebEngine
pip install PyQt5==5.11.3
Cleaning up, installing all references to Qt (Pyside, PyQT, etc), and re-installing
Attempted all the above on python 3.6 - 3.8
Here is another option, you don't have it.
Then try this option:
from PyQt5 import QtWebEngineWidgets
That is, an example of a string:
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
But, unfortunately Qt, PyQt and PySide should never be used together. Most problems occur when trying to re-display a widget created with a binding with another one created with a different binding.
The solution is simple: you either use PyQt5 and use QtWebEngineWidgets, or PySide2.
As a last resort, try installing a newer version (5.12)(PyQt5) and install PyQtWebEngine separately.
Ultimately I stuck to PySide2 (option 2), creating a new project specific python environment that did not involve PyQt5. This prevented the application from hanging with zero console errors.
When I run my Qt application I get the message
Qt WebEngine seems to be initialized from a plugin. Please set
Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute before
constructing QGuiApplication.
The app runs fine regardless of the fact that this is getting dumped to the terminal. I cant seem to find the root cause or really understand what this message is trying to tell me. What is this message saying and how can I fix it?
This can be fixed by setting AA_ShareOpenGLContexts before Spawning the QApplication.
See below an example when using PySide2
from PySide2 import QtCore, QtWidgets
if __name__ == '__main__':
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
qt_app = QtWidgets.QApplication(sys.argv)
NB: As mentioned as reply in the question: When using PyQt5, checkout https://bugreports.qt.io/browse/QTBUG-51379 instead
...
Using PySide6 instead of PySide2 solved my problem with python 3.9 and QT 5.15 if it can help
My problem is exactly the same with the problem from QtQml installation in Raspberry pi but with a little bit more confusion
I want to run a QML based GUI in raspberry PI by running a python code. I designed it with Qt creator in windows. It worked on windows but not on my raspberry pi. This is my code:
import sys
import time
from PyQt5.QtCore import QObject, QUrl, Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtQuick import QQuickView`
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("main", engine)
engine.load("main.qml")
win = engine.rootObjects()[0]
win.show()
sys.exit(app.exec_())
When I want to run it on RasPi, this happened
ImportError: No Module Found "PyQt5.QtQml
I am using a raspbian but I didn't install qt creator on the raspberry pi because I plan to design the Qt GUI in my pc to save sd card space. I only want the raspi to run the code and the gui.
in the answer here
QtQml installation in Raspberry pi it says that I have to install qtdeclerative5-dev package and the libqt5qml5.
The question is, how do I install those packages? I tried sudo apt-get but it could not locate package. The same goes for pip3.
Please help :( I'm still a newbie in this domain and in this forum
Thank you in Advance.
Well I am new to Qt and found its easier to work with python , I dont know how far its true .
but some of the code snippets have
import qt
and some have
import PyQt4
I don't know what the difference is, when I tried to interchange them I did get some errors , like some function was not recognizable and so on, also I am trying to build front end GUI for my application, which GUI framework would u suggest ? Is there anything close to VB like environment ?
Old PyQt3 use qt
import qt
Current PyQt4 use PyQt4
import PyQt4
If you use PySide, use PySide
import PySide