Кажется, ошибка, в своем ответе я попытаюсь проанализировать, что происходит.
Прежде всего я упростил MCVE до следующего:
from PySide2 import QtCore, QtGui, QtWidgets
# from PyQt5 import QtCore, QtGui, QtWidgets
class Dialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
list_widget = QtWidgets.QListWidget()
list_widget.addItems(list("ABC"))
accept_button = QtWidgets.QPushButton("Accept")
cancel_button = QtWidgets.QPushButton("Cancel")
lay = QtWidgets.QVBoxLayout(self)
hlay = QtWidgets.QHBoxLayout()
hlay.addStretch()
hlay.addWidget(accept_button)
hlay.addWidget(cancel_button)
lay.addWidget(list_widget)
lay.addLayout(hlay)
accept_button.clicked.connect(self.accepted)
cancel_button.clicked.connect(self.rejected)
def accepted(self):
print("accepted")
def rejected(self):
print("rejected")
Еще одна вещь, которую следует иметь в виду, это то, что QDialog имеет сигнал accepted()
, который вызывает это странное поведение. Также имейте в виду, что может быть установлена связь между сигналом с вызываемым, слотом и другим сигналом.
Моя гипотеза состоит в том, что PySide2 сначала устанавливает соединение со слотами и сигналами, прежде чем устанавливать соединения с обычными функциями python, и это проверяется с помощью следующего кода:
# ...
# create connections
QtCore.QObject.connect(self, QtCore.SIGNAL("accepted()"), self, QtCore.SLOT("accepted_test()"))
QtCore.QObject.connect(self, QtCore.SIGNAL("rejected()"), self, QtCore.SLOT("rejected_test()"))
def accepted_test(self):
print("accepted_test")
def rejected_test(self):
print("rejected_test")
def accepted(self):
print("accepted")
def rejected(self):
print("rejected")
# ...
Если вы нажмете кнопки «Принять» и «Отмена», вы получите:
accepted_test
rejected_test
С другой стороны, PyQt5, похоже, не имеет той же иерархии, поэтому он предпочитает соединение с функцией python.
Укажите, что ошибка субъективна, поскольку в документах явно не указано и зависит от поведения, ожидаемого каждым, возможно, это запланировано PySide2, поскольку для них это правильно, и то же самое для PyQt5.
В этом случае существует обходное решение: сделать принятую и отклоненную часть QMetaObject с помощью декоратора @QtCore.Slot()
:
# ...
accept_button.clicked.connect(self.accepted)
cancel_button.clicked.connect(self.rejected)
@QtCore.Slot()
def accepted(self):
print("accepted")
@QtCore.Slot()
def rejected(self):
print("rejected")
# ...
Но моя личная рекомендация, которую можно считать хорошей практикой, - не создавать методы, которые уже используют базовый класс.