Hi,

in the Zen of Python "Errors should never pass silently." PySide could
improve in at least two cases:

1. When deriving a Qt class with virtual methods in Python and
forgetting to implement all virtual methods the constructor returns a
object containing a Null Pointer which will inevitably cause problems
later. This Problem is particularly hard to track down for multiple
inheritance where it seems absolutely possible to create a object with
partly initialized parent objects. In that case it is very hard to
find the error since the object seems to be fully functional in the
first place.

2. Invalid return types often seems to be unchecked from the Python
side and sometimes lead to hard freezes.


Some example:

1.

When you want to create a graphics Item placable in a Layout one often
derives from both QGraphicsItem and QGraphicsLayoutItem. In that case
you have to implement the virtual methods:
    QGraphicsItem.boundingRect
    QGraphicsItem.paint
    QGraphicsLayoutItem.setGeometry
    QGraphicsLayoutItem.sizeHint

However it is perfectly possible to create objects of the following
class (to make it shorter I will use QGraphicsRectItem here, which has
already defined some usefull boundingRect and paint methods):

class TestRect(QtGui.QGraphicsRectItem, QtGui.QGraphicsLayoutItem):
    def __init__(self, *args, **kargs):
        super(TestRect, self).__init__(*args, **kargs)
        self.setRect(0, 0, 200, 100)

Then try:

>> item = TestRect()
>> print item
<PySide.QtGui.QGraphicsItem (this = 0x3328ce0 , parent = 0x0 , pos =
QPointF(0, 0) , z = 0 , flags =  ( ) )  at 0x033CF5F8>
>> scene.addItem(item)
# now the item is visible in the scene
>> layout = QtGui.QGraphicsGridLayout()
>> layout.addItem(item, 0, 0)
QGraphicsGridLayout::addItem: cannot add null item

The mechanism get's even weirder when investigating the initialization
a bit further:
For reference the following just behaves just like above:

class TestRect(QtGui.QGraphicsRectItem, QtGui.QGraphicsLayoutItem):
    pass

>> item = TestRect()
>> item.setRect(0, 0, 200, 100)
...

But the following breaks our item completely:

class TestRect(QtGui.QGraphicsRectItem, QtGui.QGraphicsLayoutItem):
    def __init__(self, *args, **kargs):
        QtGui.QGraphicsRectItem.__init__(self, *args, **kargs)
        QtGui.QGraphicsLayoutItem.__init__(self, *args, **kargs)
        self.setRect(0, 0, 200, 100)

After adding our item to the scene and trying to resize it the
following error appears and event handling seems to be broken from
there on:

QPainter::begin: Paint device returned engine == 0, type: 0

We can conclude:
 - PySide doesn't really support the super mechanism in the case of
multiple inheritance.
 - And PySide breaks silently when virtual methods are not
implemented. (Errors occur when the object is used for the first time)




2.

I have encountered the described phenomena while trying to implement
the sizeHint method of QGraphicsLayoutItem like:

class TestRect(QtGui.QGraphicsRectItem, QtGui.QGraphicsLayoutItem):
    def __init__(self, *args, **kargs):
        QtGui.QGraphicsRectItem.__init__(self, *args, **kargs)
        QtGui.QGraphicsLayoutItem.__init__(self, *args, **kargs)
        self.setRect(0, 0, 200, 100)

    def setGeometry(self, rect):
        self.setRect(rect)

    def sizeHint(self, *args):
        return self.rect()

When adding a TestRect object to the scene it breaks on resize with the error:

QPainter::begin: Paint device returned engine == 0, type: 0

The root of this problem is that sizeHint expects a QSizeF, but
QGraphicsRectItem.rect returns a QRect.
When changing the method to:

    def sizeHint(self, *args):
        return self.rect().size()

The problem is fixed.

Such an error is very hard to track down and return values should
never be passed unchecked to the c++ interface, where it can lead to
bad errors.



Regards,
Christian
_______________________________________________
PySide mailing list
[email protected]
http://lists.pyside.org/listinfo/pyside

Reply via email to