Python - 如何让这个多重继承工作?

时间:2016-12-30 13:31:50

标签: python class pyqt multiple-inheritance

我正在开发一个涉及PyQt5的项目,我正在努力管理小部件之间的继承。

我有一个QWidget屏幕,它继承了QtWidgets.QWidget和另一个由QtDesigner生成的类。它的内容如下:

class a(QtWidgets.QWidget, Ui_a):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.setupUi(self)

        <some attributes>

    <some functions

在这里,我继承了Ui_a,这是一个存储在生成文件中的单独类,我可以调用setupUiUi_a的方法)。

我现在想创建另一个类b,它也是一个需要显示的QWidget。此类b需要使用类a中的某些函数和属性。我可以轻松地复制粘贴所需的东西,但这是不好的做法,所以我正在寻找一个更整洁的解决方案。如果我做代码:

class b(QtWidgets.QWidget, Ui_b, a):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init(self, parent)
        self.setupUi(self)

然后崩溃并显示一条错误消息,指出它无法创建一致的方法解析顺序。

我的第一个问题是 - 我知道我需要调用类a的init方法,因为那里创建了a的属性,但我不知道如何。

我的第二个问题是 - 如何修复此MRO错误并成功创建可以使用b属性和函数的新类a

2 个答案:

答案 0 :(得分:5)

您试图在派生类之前混合父类。没有必要,只需直接从a和新的Ui_b继承而不是其他内容:

class b(a, Ui_b):
    # *no* __init__ needed either

a已经进入QtWidgets.QWidget

现在,Ui_aUi_b 可能不能很好地协同工作。您可能需要同时调用Ui_a.setupUi()Ui_b.setupUi()。您可以明确地这样做:

class b(a, Ui_b):
    def __init__(self, parent=None):
        super().__init__(parent)
        # Ui_b.setupUi would have shadowed Ui_a.setupUi, so 
        # call the latter explicitly
        Ui_a.setupUi(self, self)  # unbound

可能Ui_aUi_b无法混合 。在这种情况下,您应该将要重用的所有方法拉出到一个单独的基类中,并使ab继承自:

class SharedStuff:
    # ...

class a(QtWidgets.QWidget, SharedStuff, Ui_a):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.setupUi(self)

class b(QtWidgets.QWidget, SharedStuff, Ui_b):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.setupUi(self)

答案 1 :(得分:0)

您的问题有点不清楚,但我将假设Ui_aUi_b不是从Qt Designer文件生成的类 - 因为有没有理智的继承两个这样的类。

我猜你当前的课程等同于:

class A(QtWidgets.QWidget, Ui_FromQtDesigner):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.setupUi(self)

    def methodA(self):
        print('A:', self.windowTitle())

class B(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

    def methodB(self):
        print('B:', self.windowTitle())

并且您想要一个类C,它将是一个QWidget子类,它同时获取Qt Designer UI元素和类AB中的自定义方法。< / p>

现在,Qt几乎完全使用继承。从两个QWidget类继承通常是一个错误,除非这些类共享一组通用的基类(即便如此,有许多限制仍然使它成为一个有问题的设计选择 - 更多细节,请参阅this blog post)。

在你的情况下,最好使用一个简单的mixin类。只有A类才能继承QWidget,因此可以像这样定义类的集合:

class WidgetA(QtWidgets.QWidget, Ui_FromQtDesigner):
    def __init__(self, parent=None):
        super(WidgetA, self).__init__(parent)
        self.setupUi(self)

    def methodA(self):
        print('A:', self.windowTitle())

class WidgetMixinB(object):
    def methodB(self):
        print('B:', self.windowTitle())

class WidgetC(WidgetA, WidgetMixinB):
    pass

如果您还希望将WidgetMixinB用作自己的小部件,则可以为此创建另一个类:

class WidgetB(QtWidgets.QWidget, WidgetMixinB):
    pass