1 回答
TA贡献1871条经验 获得超13个赞
首先,如果使用 Qt 的信号槽自动装配机制,则使用方法QMetaObject::connectSlotsByName(),因此这种行为是由于将该函数从 C++ 转换为 Python,在 C++ 的情况下,仅 QMetaObject::connectSlotsByName() 函数连接到插槽,但在 Python 中它扩展到调用不是插槽的函数。
问题是当你点击时是一个重载信号,在 C++ 的情况下允许你使用默认参数来实现:
void QAbstractButton::clicked(bool checked = false)
但在 python 中必须使用 2 个签名:
clicked = QtCore.pyqtSignal([], [bool])
因此,在 PyQt 与插槽建立的连接中,它习惯于QMetaObject::connectSlotsByName()使用使用QMetaObject获取签名的对象的QMetaMethod,但是如果它不是插槽,您将无法获得该信息,因此该连接等效于调用。
在@pyqtSlot()具有以下签名的情况下:
@pyqtSlot()
def on_btnSlot_clicked(self):
print('slotted function call')
PyQt 建立的连接如下:
self.btnSlot.clicked.connect(self.on_btnSlot_clicked)
但如果签名@pyqtSlot(bool)是:
@pyqtSlot(bool)
def on_btnSlot_clicked(self, checked):
print('slotted function call', checked)
PyQt 建立的连接如下:
self.btnSlot.clicked[bool].connect(self.on_btnSlot_clicked)
但是如果它连接到一个不是插槽的函数,它不会考虑这些元素,因为它使用QMetaObject,因此它将与所有可能的签名建立连接。
self.btnSlot.clicked[bool].connect(self.on_btnFunc_clicked)
self.btnSlot.clicked.connect(self.on_btnFunc_clicked)
综上所述:
当QMetaObject::connectSlotsByName(...)使用时,如果它连接到@pyqtSlot(...)的签名进行验证。如果一个信号连接到一个不是 a 的函数,@pyqtSlot(...)它们将连接所有可能的签名,所以如果信号被 n 个签名重载,它将被调用 n 次。
您必须使用@pyqtSlot()以避免之前的问题,因为除了它具有快速和节省资源的优势。
添加回答
举报