QtCore.Signal 和 SIGNAL 有什么区别?
What's the difference between QtCore.Signal and SIGNAL?
我正在阅读使用 Python 和 Qt 进行快速 GUI 编程。它发布于 2008 年,在 PyQt4.5 中引入 API 更改之前。
什么是 SIGNAL()
,它与 PySide Signal()
和 PyQt 的 pyqtSignal()
class 有何不同?
我找不到任何旧文档。但是,我看到很多用于将信号连接到插槽的旧式语法:
self.connect(self, SIGNAL('valueChanged(int)'), my_slot)
我不清楚 SIGNAL
是函数、class 方法还是 class,是否用于定义新信号,以及是否仍受支持。那里有很多旧代码,我不确定如何解释。
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)
主要区别是:
- 验证 run-time 或 compile-time、
中信号和槽的存在
- 如果插槽不一定是QSlot,可以是任何函数。
有关详细信息,请阅读 here。目前推荐第二种方法,因为它预见到错误。
考虑到上述情况,PyQt4 的最新版本和 PyQt5 从一开始就通过允许声明信号的 pyqtSignal(PySide 中的信号)实现了新的声明语法。
总之,SIGNAL 是在 PySide2 中仍然有效但在 PyQt5 中不再有效的旧连接样式的残余,此方法允许在运行时创建信号。另一方面,pyqtSignal 或 Signal 允许我们在创建 class.
时声明信号
以下示例显示了差异:
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,而是使用新语法。
我正在阅读使用 Python 和 Qt 进行快速 GUI 编程。它发布于 2008 年,在 PyQt4.5 中引入 API 更改之前。
什么是 SIGNAL()
,它与 PySide Signal()
和 PyQt 的 pyqtSignal()
class 有何不同?
我找不到任何旧文档。但是,我看到很多用于将信号连接到插槽的旧式语法:
self.connect(self, SIGNAL('valueChanged(int)'), my_slot)
我不清楚 SIGNAL
是函数、class 方法还是 class,是否用于定义新信号,以及是否仍受支持。那里有很多旧代码,我不确定如何解释。
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)
主要区别是:
- 验证 run-time 或 compile-time、 中信号和槽的存在
- 如果插槽不一定是QSlot,可以是任何函数。
有关详细信息,请阅读 here。目前推荐第二种方法,因为它预见到错误。
考虑到上述情况,PyQt4 的最新版本和 PyQt5 从一开始就通过允许声明信号的 pyqtSignal(PySide 中的信号)实现了新的声明语法。
总之,SIGNAL 是在 PySide2 中仍然有效但在 PyQt5 中不再有效的旧连接样式的残余,此方法允许在运行时创建信号。另一方面,pyqtSignal 或 Signal 允许我们在创建 class.
时声明信号以下示例显示了差异:
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,而是使用新语法。