【问题标题】:Declaration of the custom Signals自定义信号的声明
【发布时间】:2021-01-01 13:52:45
【问题描述】:

在 Qt 中,我们可以通过将它们设为静态变量来创建自定义信号。然后我们使用self.signame 而不是classname.signame。 这样就在类中创建了一个实例变量。

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

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

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

【问题讨论】:

  • 我已经编辑了一点。估计现在还好。
  • 我已经使用了这段代码,我没有遇到任何问题。注意:错误信息永远不会和你提供的代码匹配,你确定这个错误信息是用你提供的代码得到的吗?
  • 给定的伪代码没有任何错误,但是如果我们通过取消注释 #1 并删除静态变量来进行一些修改,我们会得到错误。我将添加更多代码
  • mmm,既然PyQt明明不推荐,为什么还要把信号声明为属性呢?

标签: python pyqt pyqt5


【解决方案1】:

需要注意的是,pyqtSignal 被声明为类的一个属性,但它与the docs 中指示的连接中使用的对象不同:

信号(特别是未绑定信号)是一个类属性。当一个 信号被引用为类实例的属性然后 PyQt5 自动将实例绑定到信号,以便 创建一个绑定信号。这与 Python 本身的机制相同 用于从类函数创建绑定方法。

绑定信号具有 connect()、disconnect() 和 emit() 方法 实现相关功能。它还具有信号属性 这是 Qt 将返回的信号的签名 SIGNAL() 宏。

换句话说,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'>

总之,类“sig”的属性是一个没有connect方法的pyqtSignal,用来构造属性“self.x”,它是一个有connect方法的pyqtBoundSignal。

【讨论】:

  • 谢谢,我明白了。因此对象可以具有相同未绑定信号的不同绑定信号(绑定到差异函数)
  • 不要对 [un]bound 的含义感到困惑:这个词不是指信号所连接的对象,而是指 与实例 的绑定。所有信号都可以连接到不同的功能(也可以多次连接到同一个功能,如果不是出于非常具体的原因,应该避免这种情况)
猜你喜欢
  • 2021-12-12
  • 2018-11-12
  • 1970-01-01
  • 2021-09-09
  • 2021-06-25
  • 2015-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多