【问题标题】:What's the difference between QtCore.Signal and SIGNAL?QtCore.Signal 和 SIGNAL 有什么区别?
【发布时间】:2021-02-11 10:49:39
【问题描述】:

我正在阅读使用 Python 和 Qt 进行快速 GUI 编程。它于 2008 年发布,早于 PyQt4.5 中引入的 API 更改。

SIGNAL() 是什么?它与 PySide Signal() 和 PyQt 的 pyqtSignal() 类有何不同?

我找不到任何旧文档。但是,我看到了很多用于将信号连接到插槽的旧式语法:

self.connect(self, SIGNAL('valueChanged(int)'), my_slot)

我不清楚SIGNAL 是函数、类方法还是类,它是否用于定义新信号,以及它是否仍受支持。那里有很多旧代码我不知道如何解释。

【问题讨论】:

    标签: python pyqt pyside


    【解决方案1】:

    SIGNAL 是一种实现 Qt 宏 SIGNAL 的方法,它存在于 PyQt4 / PySide / PySide2 中,而不再存在于 pyqt5 中。

    要了解区别,就必须了解Qt中不同的连接语法:

    • 旧式:
    connect(sender, SIGNAL(foo_signal(parameters)), receiver, SLOT(foo_slot(parameters))
    
    • 新风格:
    connect(sender, &Sender_Klass::foo_signal, receiver, &Receiver_Klass::foo_slot)
    

    主要区别在于:

    • 在运行时或编译时验证信号和槽的存在,
    • 如果插槽不一定是 QSlot 但它们可以是任何函数。

    更多信息请阅读here。目前推荐使用第二种方法,因为它可以预见错误。


    考虑到上述情况,PyQt4 的最后一个版本和从一开始 PyQt5 通过允许声明信号的 pyqtSignal(PySide 中的信号)实现了新的声明语法。

    总之,SIGNAL 是旧连接方式的残余,在 PySide2 中仍然有效,但在 PyQt5 中不再有效,这种方法允许在运行时创建信号。另一方面,pyqtSignal 或 Signal 允许我们在创建类时声明信号。

    以下示例显示了差异:

    from PySide2 import QtCore
    
    
    class Foo(QtCore.QObject):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.connect(self, QtCore.SIGNAL("foo()"), self.slot_foo)
    
        def slot_foo(self):
            print("bye")
            QtCore.QCoreApplication.quit()
    
    
        def send_signal(self):
            self.emit(QtCore.SIGNAL("foo()"))
    
    app = QtCore.QCoreApplication([])
    foo = Foo()
    QtCore.QTimer.singleShot(1000, foo.send_signal)
    app.exec_()
    
    from PySide2 import QtCore
    
    
    class Foo(QtCore.QObject):
        foo = QtCore.Signal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.foo.connect(self.slot_foo)
    
        def slot_foo(self):
            print("bye")
            QtCore.QCoreApplication.quit()
    
        def send_signal(self):
            self.foo.emit()
    
    
    app = QtCore.QCoreApplication([])
    foo = Foo()
    QtCore.QTimer.singleShot(1000, foo.send_signal)
    app.exec_()
    

    更详细地说,第一种方法在运行时创建修改 QMetaObject 的信号,这可能会导致问题,因为 QMetaObject 具有可以在某些优化中考虑的预定顺序。因此,当使用第一种方法时,它会发出警告并失败:

    from PySide2 import QtCore
    
    
    class Foo(QtCore.QObject):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.connect(self, QtCore.SIGNAL("bar()"), self.slot_bar)
            self.connect(self, QtCore.SIGNAL("foo()"), self.slot_foo)
    
        def slot_foo(self):
            print("ok")
            self.emit(QtCore.SIGNAL("foo()"))
    
        def slot_bar(self):
            print("bye")
            QtCore.QCoreApplication.quit()
    
        def send_signal(self):
            print("send foo signal")
            self.emit(QtCore.SIGNAL("foo()"))
    
    app = QtCore.QCoreApplication([])
    foo = Foo()
    QtCore.QTimer.singleShot(1000, foo.send_signal)
    app.exec_()
    
    main.py:8: RuntimeWarning: 
    
    *** Sort Warning ***
    Signals and slots in QMetaObject 'Foo' are not ordered correctly, this may lead to issues.
    1  Signal bar()
    2  Slot   slot_bar()
    3! Signal foo()
    
      self.connect(self, QtCore.SIGNAL("foo()"), self.slot_foo)
    main.py:8: RuntimeWarning: 
    
    *** Sort Warning ***
    Signals and slots in QMetaObject 'Foo' are not ordered correctly, this may lead to issues.
    1  Signal bar()
    2  Slot   slot_bar()
    3! Signal foo()
    4! Slot   slot_foo()
    
      self.connect(self, QtCore.SIGNAL("foo()"), self.slot_foo)
    main.py:26: RuntimeWarning: 
    
    *** Sort Warning ***
    Signals and slots in QMetaObject 'Foo' are not ordered correctly, this may lead to issues.
    1  Signal bar()
    2  Slot   slot_bar()
    3! Signal foo()
    4! Slot   slot_foo()
    5! Slot   send_signal()
    
      app.exec_()
    send
    

    因此,目前不建议在最新版本的 PySide2 和 PyQt5 中使用 SIGNAL,而是使用新语法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 2011-12-12
      • 2010-09-16
      • 2012-03-14
      相关资源
      最近更新 更多