Reputation: 554
In Qt, we can create custom signals by making them static variables. and then we use self.signame
instead classname.signame
.
So that creates an instance variable in the class.
I wanted to know the theory beyond this pattern.
here's some pseudo-code that I have tried that was recorded in most of the sources:
from PyQt5 import QtWidgets,QtCore
class test(QtWidgets.QApplication):
sig=QtCore.pyqtSignal([bool])
def __init__(self):
super().__init__([])
# self.sig=QtCore.pyqtSignal([bool]) #1
self.window=QtWidgets.QWidget()
self.sig.connect(lambda x=True:print('Hello World'))
self.bt=QtWidgets.QPushButton(self.window,text='test',clicked=self.sig)
self.window.setLayout(QtWidgets.QVBoxLayout())
self.window.layout().addWidget(self.bt)
self.window.show()
test().exec()
When i tred to access the signal test.sig
instead of self.sig
,
from PyQt5 import QtWidgets,QtCore
class test(QtWidgets.QApplication):
def __init__(self):
super().__init__([])
self.sig=QtCore.pyqtSignal([bool])
self.window=QtWidgets.QWidget()
self.sig.connect(lambda x=True:print('Hello World'))
self.bt=QtWidgets.QPushButton(self.window,text='test',clicked=self.sig)
self.window.setLayout(QtWidgets.QVBoxLayout())
self.window.layout().addWidget(self.bt)
self.window.show()
test().exec()
i get this error:
test.sig.connect(lambda x=True:print('Hello World'))
AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'
and when I tried to make the signal as an instance variable instead of the static variable I get that error (uncommenting the #1 in psudeo code)
I get the same error (as before).
May I know the reason behind this
Source: PyQt5
Upvotes: 0
Views: 742
Reputation: 244301
It should be noted that pyqtSignal is declared as an attribute of the class but it is not the same object that is used in the connection as indicated in the docs:
A signal (specifically an unbound signal) is a class attribute. When a signal is referenced as an attribute of an instance of the class then PyQt5 automatically binds the instance to the signal in order to create a bound signal. This is the same mechanism that Python itself uses to create bound methods from class functions.
A bound signal has connect(), disconnect() and emit() methods that implement the associated functionality. It also has a signal attribute that is the signature of the signal that would be returned by Qt’s SIGNAL() macro.
In other words, sig = QtCore.pyqtSignal([bool])
is an unbound signal but self.sig
is the bound signal and that can be verified with the following lines:
from PyQt5 import QtWidgets, QtCore
class test(QtWidgets.QApplication):
sig = QtCore.pyqtSignal([bool])
print(type(sig))
def __init__(self):
super().__init__([])
self.window = QtWidgets.QWidget()
print(type(self.sig))
self.sig.connect(lambda x=True: print("Hello World"))
self.bt = QtWidgets.QPushButton(self.window, text="test", clicked=self.sig)
self.window.setLayout(QtWidgets.QVBoxLayout())
self.window.layout().addWidget(self.bt)
self.window.show()
test().exec()
Output
<class 'PyQt5.QtCore.pyqtSignal'>
<class 'PyQt5.QtCore.pyqtBoundSignal'>
In conclusion, the attribute of the class "sig" is a pyqtSignal that does not have the connect method and that is used to construct the attribute "self.x" which is a pyqtBoundSignal that does have the connect method.
Upvotes: 2