PyQt5,Qt 5.9.6发生以下问题。
我想基于另一个类(Dialog
)生成模式对话框类(UserForm
)。但是,如果UserForm
已经继承自QWidget
,则我的脚本会引发异常
“对话框”对象没有属性“ exec _”
或者只是默默崩溃或在控制台中崩溃并显示消息:
QDialog :: exec:检测到递归调用
如果UserForm
是否从QWidget继承,则MRO看起来完全相同:
(<class '__main__.Dialog'>, <class '__main__.UserForm'>, <class
'PyQt5.QtWidgets.QDialog'>, <class 'PyQt5.QtWidgets.QWidget'>, <class
'PyQt5.QtCore.QObject'>, <class 'sip.wrapper'>, <class
'PyQt5.QtGui.QPaintDevice'>, <class 'sip.simplewrapper'>, <class 'object'>)
示例:
from PyQt5 import QtWidgets
app = QtWidgets.QApplication([])
class UserForm(QtWidgets.QWidget):
pass
# class Dialog(UserForm, QtWidgets.QDialog):
# pass
Dialog = type("Dialog", (UserForm, QtWidgets.QDialog), {})
print(Dialog.__mro__)
Dialog().exec_()
我还尝试使用Qt 5.12的PySide2运行此代码,它可以正常工作。这是否意味着PyQt中存在一些错误?
答案 0 :(得分:2)
相反,这是PySide2的错误,因为它与docs相矛盾:
多重继承要求QObject首先出现
如果您正在使用 多重继承,moc假定第一个继承的类是 QObject的子类。另外,请确保只有第一个继承的类 是一个QObject。
如果考虑到上一部分中描述的行为,则Dialog类应仅考虑UserForm而不考虑QDialog,因此Dialog不应具有exec_()方法,因为只有从QDialog继承的类才可以拥有它。 >
在Qt中,您不应该从2个QObject继承,仅支持混合(QObject +不支持QObject)(1)(2)。
如果是mixin,则第一个必须是QObject。
这就是pyuic继承的模式:
from PyQt5 import QtCore, QtGui, QtWidgets
# or
# from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(30, 240, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
self.buttonBox.setObjectName("buttonBox")
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
def init(self, parent=None):
super(self.__class__, self).__init__(parent)
self.setupUi(self)
# or
# class Dialog(QtWidgets.QDialog, Ui_Dialog):
# def __init__(self, parent=None):
# super(Dialog, self).__init__(parent)
# self.setupUi(self)
Dialog = type("Dialog", (QtWidgets.QDialog, Ui_Dialog), {"__init__": init})
if __name__ == "__main__":
app = QtWidgets.QApplication([])
Dialog().exec_()