自定义信号的声明

Declaration of the custom Signals

在 Qt 中,我们可以通过将它们设为静态变量来创建自定义信号。然后我们使用 self.signame 代替 classname.signame。 这样就在 class.

中创建了一个实例变量

我想知道这个模式之外的理论。

这是我尝试过的一些伪代码,这些伪代码记录在大多数来源中:

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()

当我尝试访问信号 test.sig 而不是 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()

我收到这个错误:

    test.sig.connect(lambda x=True:print('Hello World'))
AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'

当我试图将信号作为实例变量而不是静态变量时,我得到了那个错误(取消注释伪代码中的#1)

我得到了同样的错误(和以前一样)。

请问这背后的原因

来源:PyQt5

需要注意的是,pyqtSignal 被声明为 class 的属性,但它与 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.

换句话说,sig = QtCore.pyqtSignal([bool]) 是一个未绑定的信号,但 self.sig 是绑定的信号,可以用以下几行来验证:

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()

输出

<class 'PyQt5.QtCore.pyqtSignal'>
<class 'PyQt5.QtCore.pyqtBoundSignal'>

总之,class“sig”的属性是一个没有连接方法的pyqtSignal,用于构造属性“self.x”,它是一个pyqtBoundSignal确实有连接方法。