Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: RuntimeError: super-class __init__() of %S was never called

I tried to do some operation (setParent) on an object in Python (an instance of a class which inherits from a different class - to be specific, QtGui.QLabel), but during runtime the above error was raised. The object itself has had some fields with actual content (verified on debug), but from some reason I couldn't "use" it. What does the error mean and how can I fix it? For some additional information, I shall say that the object was returned from a static method before I tried to do this operation on it.

The subclass has a __init__() function of its own:

def __init__(self, image, father):
        super(AtomicFactory.Image, self).__init__(father)
        self.raw_attributes = image.attributes
        self.attributes = {}
        father.addChild(self)
        self.update()

Now I wrote a similar code, a simple one, that had the same error on the line widget.setParent(mw) when the window was moved.

#!/usr/bin/env python
import sys
import copy
from PyQt4 import QtCore, QtGui

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    main_widget=QtGui.QWidget()
    widget = QtGui.QPushButton('Test')
    widget.resize(640, 480)
    widget.setParent(main_widget)
    widget.move(0, 0)
    widget2=QtGui.QPushButton('Test2')
    widget2.i=0
    widget2.resize(600, 200)
    widget2.setParent(main_widget)
    widget2.move(640, 0)
    def onResize(event):
        print event
        mw=copy.deepcopy(main_widget)
        widget.setParent(mw)
        widget2.setParent(mw)
        widget.move(0, 0)
        widget2.move(640, 480)
        main_widget_width=main_widget.width()
        widget_width=widget.width()
        width2=main_widget_width-widget_width
        height2=widget2.height()
        widget2.resize(width2, height2)
        widget2.move(640, 0)
    main_widget.resizeEvent=onResize
    def onClick():
        size=(widget2.width(), widget2.height())
        if(widget2.i%2==0):
            widget2.resize(int(size[0]/2), int(size[1]/2))
        else:
            widget2.resize(size[0]*2, size[1]*2)
        widget2.i+=1
    QtCore.QObject.connect(widget, QtCore.SIGNAL('clicked()'), onClick)
    main_widget.show()
    sys.exit(app.exec_())

What was the problem?

like image 414
Tomer Avatar asked Sep 05 '12 11:09

Tomer


1 Answers

If you want to inherit QObject (or QWidget), you must always call the super-class __init__:

class MyObject(QObject):
    def __init__(self, *args, **kwargs):
        super(MyObject, self).__init__(arguments to parent class)
        #other stuff here

You may also call the parent's class's __init__ after some instructions, but you can't call QObject methods or use QObject attributes until you did so.


Edit: In your case you are trying to deepcopy a QWidget, but this is not possible. Python may be able to copy the wrapper of the QWidget, but the QWidget itself is a C++ object that python cannot handle with the default implementation of copy.deepcopy, hence whenever you call a method of the copied instance you get the RuntimeError because the underlying C++ object wasn't initialized properly.

The same is true for pickling these objects. Python is able to pickle the wrapper, not the C++ object itself, hence when unpickling the instance the result is a corrupted instance.

In order to support deepcopy() the QWidget class should implement the __deepcopy__ method, but it does not do that.

If you want to copy widgets you'll have to implement by yourself all the mechanism by hand.

like image 81
Bakuriu Avatar answered Oct 24 '22 18:10

Bakuriu