[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Re: [PyKDE] PyQt4 problems with underlying C/C++ objects [weird]
From:       "Krystian Samp" <samp.krystian () gmail ! com>
Date:       2006-11-21 14:57:47
Message-ID: cfa896710611210657m65cd2b28q73c3a4f807f0e220 () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hi,
thanks for the answer. When I commented the line which adds MyItem2 to the
scene the effect was the same - the underlying C/C++ object was destructed.
It is weird but I found some interesting notes on this problem:
http://www.nanoengineer-1.net/mediawiki/index.php?title=Qt_4_mysteries#One_mystery_solved

It seems that when you create an item the python object holds a reference to
it. However, if you assign that item to a hierarchy of items (for instance
using setParentItem()) the python object loses (or you can say hands over)
the reference. This reference still exists in the C/C++ level in the
hierarchy but only there. So If you stop referencing to the parent of the
item then the item itself will be destroyed as well. This is weird since you
still have a python object representing the item but as I said it handed
over the reference to the C/C++ layer. This is my observation and I think
it's not a good behavior of PyQt since you actually have to think about
C/C++ and the principle I've described.

so for the above code snippet it is sufficient to detach children items from
the parent before deleting the parent.

any comments? your observations?

best regards,
Krystian

2006/11/21, Phil Thompson <phil@riverbankcomputing.co.uk>:
>
> On Sunday 19 November 2006 10:18 pm, Krystian Samp wrote:
> > Hi all,
> >
> > I've got the following error:
> >
> > Traceback (most recent call last):
> >   File "test2.py", line 47, in mousePressEvent
> >     item = MyItem2(self.options)
> >   File "test2.py", line 10, in __init__
> >     i.setParentItem(self)
> > RuntimeError: underlying C/C++ object has been deleted
> >
> > for this code (I've tried to make it as short as possible):
> >
> > import sys
> > from PyQt4 import QtGui, QtCore
> >
> > class MyItem2(QtGui.QGraphicsItem):
> >     def __init__(self, items):
> >         QtGui.QGraphicsItem.__init__(self)
> >
> >         self.items = items
> >         for i in self.items:
> >             i.setParentItem(self)
> >
> >     def paint(self, painter, option, widget):
> >         painter.drawEllipse(0, 0, 10, 10)
> >
> >     def boundingRect(self):
> >         return QtCore.QRectF(0, 0, 20, 20)
> >
> >
> > class MyItem1(QtGui.QGraphicsItem):
> >     def __init__(self):
> >         QtGui.QGraphicsItem.__init__(self)
> >
> >     def paint(self, painter, option, widget):
> >         painter.drawEllipse(0, 0, 20, 20)
> >
> >     def boundingRect(self):
> >         return QtCore.QRectF(0, 0, 20, 20)
> >
> >
> > class MyItem(QtGui.QGraphicsItem):
> >     def __init__(self, options):
> >         QtGui.QGraphicsItem.__init__(self)
> >
> >         self.options = options
> >         self.activated = False
> >         self.items = []
> >
> >     def paint(self, painter, option, widget):
> >         pass
> >
> >     def boundingRect(self):
> >         return QtCore.QRectF(-100, -100, 200, 200)
> >
> >     def mousePressEvent(self, event):
> >         self.activated = not self.activated
> >         if self.activated:
> >             item = MyItem2(self.options)
> >             self.scene().addItem(item)
> >             self.items.append(item)
> >             item.setParentItem(self)
> >         if not self.activated:
> >             for i in self.items:
> >                 i.setParentItem(None)
> >                 self.scene().removeItem(i)
> >             self.items = []
> >
> > class MyView(QtGui.QGraphicsView):
> >     def __init__(self):
> >         QtGui.QGraphicsView.__init__(self)
> >
> >         self.scene = QtGui.QGraphicsScene()
> >
> >         self.items = [MyItem1(), MyItem1(), MyItem1()]
> >         self.item = MyItem(self.items)
> >
> >         self.scene.addItem(self.item)
> >         self.setScene(self.scene)
> >
> > # main program
> > app = QtGui.QApplication(sys.argv)
> > view = MyView()
> > view.show()
> >
> > sys.exit(app.exec_())
> >
> > After running it, click several times on the 'canvas' to see the error.
> > It is strange. The error concerns objects which I hold in MyItem.objects.
> I
> > do not understand why the underlying objects are lost. Can anyone
> explain
> > me that?
> > Moreover if I comment the line 'self.items = []' then there is no such
> > error. Is it possible that this assignment destroys C/C++ objects under
> the
> > curtain? Hard to believe.
>
> You are adding MyItem2 to the scene and setting its parent to MyItem. My
> understanding is that you do one or the other. If I'm wrong then there is
> probably a bug in the ownership transfer flags.
>
> Phil
>

[Attachment #5 (text/html)]

Hi,<br>thanks for the answer. When I commented the line which adds MyItem2 to the \
scene the effect was the same - the underlying C/C++ object was destructed. It is \
weird but I found some interesting notes on this problem:  <a \
href="http://www.nanoengineer-1.net/mediawiki/index.php?title=Qt_4_mysteries#One_myste \
ry_solved">http://www.nanoengineer-1.net/mediawiki/index.php?title=Qt_4_mysteries#One_mystery_solved</a><br><br>It \
seems that when you create an item the python object holds a reference to it. \
However, if you assign that item to a hierarchy of items (for instance using \
setParentItem()) the python object loses (or you can say hands over) the reference. \
This reference still exists in the C/C++ level in the hierarchy but only there. So If \
you stop referencing to the parent of the item then the item itself will be destroyed \
as well. This is weird since you still have a python object representing the item but \
as I said it handed over the reference to the C/C++ layer. This is my observation and \
I think it's not a good behavior of PyQt since you actually have to think about C/C++ \
and the principle I've described. <br><br>so for the above code snippet it is \
sufficient to detach children items from the parent before deleting the \
parent.<br><br>any comments? your observations?<br><br>best \
regards,<br>Krystian<br><br><div><span class="gmail_quote"> 2006/11/21, Phil Thompson \
&lt;<a href="mailto:phil@riverbankcomputing.co.uk">phil@riverbankcomputing.co.uk</a>&gt;:</span><blockquote \
class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt \
0pt 0.8ex; padding-left: 1ex;"> On Sunday 19 November 2006 10:18 pm, Krystian Samp \
wrote:<br>&gt; Hi all,<br>&gt;<br>&gt; I've got the following error:<br>&gt;<br>&gt; \
Traceback (most recent call last):<br>&gt;&nbsp;&nbsp; File &quot;test2.py&quot;, \
line 47, in mousePressEvent <br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; item = \
MyItem2(self.options)<br>&gt;&nbsp;&nbsp; File &quot;test2.py&quot;, line 10, in \
__init__<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; i.setParentItem(self)<br>&gt; RuntimeError: \
underlying C/C++ object has been deleted<br>&gt;<br>&gt; for this code (I've tried to \
make it as short as possible): <br>&gt;<br>&gt; import sys<br>&gt; from PyQt4 import \
QtGui, QtCore<br>&gt;<br>&gt; class \
MyItem2(QtGui.QGraphicsItem):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def __init__(self, \
items):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
QtGui.QGraphicsItem.__init__(self)<br>&gt;<br> \
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.items = \
items<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in \
self.items:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
i.setParentItem(self)<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def paint(self, \
painter, option, widget):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
painter.drawEllipse(0, 0, 10, 10) <br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
boundingRect(self):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return \
QtCore.QRectF(0, 0, 20, 20)<br>&gt;<br>&gt;<br>&gt; class \
MyItem1(QtGui.QGraphicsItem):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
__init__(self):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
QtGui.QGraphicsItem.__init_ _(self)<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
paint(self, painter, option, \
widget):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
painter.drawEllipse(0, 0, 20, 20)<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
boundingRect(self):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return \
QtCore.QRectF(0, 0, 20, 20)<br>&gt; <br>&gt;<br>&gt; class \
MyItem(QtGui.QGraphicsItem):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def __init__(self, \
options):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
QtGui.QGraphicsItem.__init__(self)<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.options = options<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.activated  = False<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.items = []<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def paint(self, painter, \
option, widget):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
pass<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
boundingRect(self):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return \
QtCore.QRectF(-100, -100, 200, 200) <br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
mousePressEvent(self, event):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.activated = not \
self.activated<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if \
self.activated:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
item = MyItem2(self.options)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.scene ().addItem(item)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.items.append(item)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
item.setParentItem(self)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if \
not self.activated:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
for i in self.items:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
i.setParentItem (None)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.scene().removeItem(i)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.items = []<br>&gt;<br>&gt; class \
MyView(QtGui.QGraphicsView):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def \
__init__(self):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
QtGui.QGraphicsView.__init__(self) \
<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.scene = \
QtGui.QGraphicsScene()<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.items = [MyItem1(), MyItem1(), \
MyItem1()]<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.item = \
MyItem(self.items)<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.scene.addItem (self.item)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
self.setScene(self.scene)<br>&gt;<br>&gt; # main program<br>&gt; app = \
QtGui.QApplication(sys.argv)<br>&gt; view = MyView()<br>&gt; \
view.show()<br>&gt;<br>&gt; sys.exit(app.exec_())<br>&gt;<br> &gt; After running it, \
click several times on the 'canvas' to see the error.<br>&gt; It is strange. The \
error concerns objects which I hold in MyItem.objects. I<br>&gt; do not understand \
why the underlying objects are lost. Can anyone explain <br>&gt; me that?<br>&gt; \
Moreover if I comment the line 'self.items = []' then there is no such<br>&gt; error. \
Is it possible that this assignment destroys C/C++ objects under the<br>&gt; curtain? \
Hard to believe.<br><br> You are adding MyItem2 to the scene and setting its parent \
to MyItem. My<br>understanding is that you do one or the other. If I'm wrong then \
there is<br>probably a bug in the ownership transfer \
flags.<br><br>Phil<br></blockquote> </div><br>



_______________________________________________
PyKDE mailing list    PyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic