anonymous | 2020-05-11 07:09:23 UTC | #1
Is there any reason why signals of WorkerSignals are class variables?
martin | 2020-09-11 20:41:22 UTC | #2
This is actually due to how PyQt5 (and PySide2) hook up signals and create Qt objects, and how the order of that relates to their related Python objects.
When you define a signal on a class, e.g.
class MyWindow(QMainWindow):
my_custom_signal = pyqtSignal()
You are creating an instance of pyqtSignal
and assigning it to the class variable my_custom_signal
. However, nothing is happening in Qt here, this is just a simple Python object.
When you create an instance of your MyWindow
class the Python object is created, the __init__
is run, the super()
class is called and then PyQt5 creates the Qt objects, and hooks everything together. At this point PyQt5 searches for signal definitions on the object, and hooks these up using Qt signals (with appropriate magic).
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
If you defined signals in your __init__
like you might expect...
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.my_custom_signal = pyqtSignal()
this won't work.... because when you call the super init, PyQt5 will try and hook up the signals, but you haven't defined them yet.
Of course, PyQt5 could require you have to put the super().__init__
call after you've created the signals....
class MyWindow(QMainWindow):
def __init__(self):
self.my_custom_signal = pyqtSignal()
super().__init__()
...but that's surprising and not very nice.
Putting them on the class side-steps all this.
Packaging Python Applications with PyInstaller by Martin Fitzpatrick — This step-by-step guide walks you through packaging your own Python applications from simple examples to complete installers and signed executables.