Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PySide, PysideUIC and Multiple Inheritance

I have a dialog class that is inheriting a pyside-uic-generated python class but my problem is that it cannot be extended my adding another base class.

import sys
from PySide import QtGui
from mi_ui import Ui_Dialog

class Worker(object):
    def __init__(self):
        super(Worker, self).__init__()
        self.data = 1

class MainDialog(QtGui.QDialog, Ui_Dialog, Worker):
    def __init__(self):
        super(MainDialog, self).__init__()
        self.setupUi(self)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dlg = MainDialog()
    print dlg.data
    dlg.show()

    sys.exit(app.exec_())

When I try to extend MainDialog with Worker, super does not call the Worker's __init__ and the print dlg.data fails because "AttributeError: 'MainDialog' object has no attribute 'data'"

My only work around seems to ignore super and invoke each __init__ manually.

QtGui.QDialog.__init__(self)
Worker.__init__(self)

Is this my only solution?

This is for Python 2.7.

like image 584
E.Beach Avatar asked Nov 02 '22 09:11

E.Beach


2 Answers

Multiple inheritance is tricky in python. The classes that you are inheriting from cannot have any conflicts if you want it to work perfectly. In most cases multiple inheritance with pyside does cause a conflict because everything inherits QObject giving identical variables and methods. Python doesn't know which one to inherit. The painting is another area for conflict. The other thing to consider is the order of the inheritance. I believe that python tries inheritance and init from left to right. So if you only want the init method for the QtGui.QDialog and the Worker (Ui_Dialog will probably conflict) then you might want to try.

class MainDialog(QtGui.QDialog, Worker, Ui_Dialog):

In python 3 you can call the super method a little differently.

class MainDialog(QtGui.QDialog, Worker, Ui_Dialog):
    super().__init__()

I believe that the way you are calling the init for 2.7 is the correct way of doing things. Questions similar to this are all over the place. It is a common problem known as the Diamond problem. Python super method and calling alternatives may explain things a little more.

like image 50
justengel Avatar answered Nov 15 '22 05:11

justengel


Make Worker the first base-class:

class MainDialog(Worker, QtGui.QDialog, Ui_Dialog)

This will still result in MainDialog.__init__ being called first, then Worker.__init__ (which can see if you add some print statements). But you will still be able to access the data attribute from inside the MainDialog.__init__.

The Ui_Dialog class doesn't really figure in any of this, because it is just an ordinary python class inheriting from object and doesn't ever call super. So it can go anywhere you like in the base-class order.

Obviously, if you do things this way, you will have to take care not to clobber any methods from the other base-classes in the Worker class - but you already had this "problem" anyway (just in a different order).

like image 40
ekhumoro Avatar answered Nov 15 '22 05:11

ekhumoro