Прежде всего, если используется механика автопровода 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(...)
, подписи проверяются. Если сигнал подключен к функции, отличной от @pyqtSlot(...)
, он соединится со всеми возможными сигнатурами, поэтому, если сигнал перегружен n сигнатурами, он будет вызван n раз.
Вы должны использовать @pyqtSlot()
, чтобы избежать предыдущей проблемы, так как кроме этого у нее есть преимущества для быстроты и экономии ресурсов.