关于类:Python – 如何使这个多重继承工作?

Python - how to get this multiple inheritance to work?

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

我有一个qwidget屏幕继承了qtwidgets.qwidget,还有一个由qtdesigner生成的类。它的内容如下:

1
2
3
4
5
6
7
8
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,一个存储在生成文件中的独立类,我可以调用setupUi(Ui_a的方法)fine。

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

1
2
3
4
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的属性和函数?


您试图在派生类之前混入父类。无需直接继承a和新Ui_b的遗产,无需继承其他遗产:

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

a已经拉入QtWidgets.QWidget

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

1
2
3
4
5
6
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

1
2
3
4
5
6
7
8
9
10
11
12
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)


你的问题有点不清楚,但我假设Ui_aUi_b不是从qt设计器文件生成的两个类,因为没有从这两个类继承的明智方法。

我猜你目前的课程相当于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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子类,从类ab中获取qt设计器UI元素和自定义方法。

现在,qt几乎只使用单一继承。从两个QWidget类继承通常是一个错误,除非这些类共享一组公共的基类(即便如此,仍然存在许多限制,使其成为一个有问题的设计选择-有关更多详细信息,请参阅此博客文章)。

在您的例子中,最好使用一个简单的mixin类。类a确实需要从QWidget继承,所以类集可以这样定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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本身作为一个小部件使用,您可以为它创建另一个类,如下所示:

1
2
class WidgetB(QtWidgets.QWidget, WidgetMixinB):
    pass