【问题标题】:Python - how to get this multiple inheritance to work?Python - 如何让这种多重继承发挥作用?
【发布时间】:2017-05-14 19:23:11
【问题描述】:

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

我有一个继承 QtWidgets.QWidget 的 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 错误并成功创建可以使用 a 的属性和函数的新类 b

【问题讨论】:

标签: python class pyqt multiple-inheritance


【解决方案1】:

您试图在派生类之前混合父类。没必要,直接继承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)

【讨论】:

  • 说“Ui_aUi_b 可能不能很好地协同工作”如果它们都是从 qt 设计器文件中生成的(这就是 setupUi 方法的来源),那是相当轻描淡写的。使用相同的参数多次调用setupUi 通常是不安全的(尽管它可能仍然“工作”通过纯粹的愚蠢运气)。
  • @ekhumoro:我对 qt 的经验是 0,更不用说自动生成的代码了。添加了一个替代选项。
【解决方案2】:

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

我猜你现在的课程是这样的:

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 的自定义方法。

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

在您的情况下,最好使用简单的 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 2020-04-07
    相关资源
    最近更新 更多