[PyKDE] Re: Signal destroyed() not emitted for QWidget

Phil Thompson phil at riverbankcomputing.co.uk
Tue Feb 14 16:09:45 GMT 2006


On Tuesday 14 February 2006 2:45 pm, Giovanni Bajo wrote:
> Phil,
>
> Using PyQt snapshot-20051212 and SIP snapshot-20051212, I found this bug:
>
> ----------------------------------------------------
> from qt import *
>
> app = QApplication([])
>
> def testDestruction(cls):
>     def foo(o):
>         print "destroyed:", o
>         destroyed.append(o)
>
>     destroyed = []
>     o = cls(None)
>     QObject.connect(o, SIGNAL("destroyed(QObject*)"), foo)
>     o.deleteLater()
>     qApp.sendPostedEvents(o, QEvent.DeferredDelete)
>     assert destroyed
>
> testDestruction(QObject)
> testDestruction(QWidget)
> ----------------------------------------------------
> destroyed: <qt.QObject object at 0x089964F8>
> Traceback (most recent call last):
>   File "D:\Work\caligola3d\src\pyqtbug8.py", line 19, in ?
>     testDestruction(QWidget)
>   File "D:\Work\caligola3d\src\pyqtbug8.py", line 16, in testDestruction
>     assert destroyed
> AssertionError
>
>
> To me, it looks like the signal "destroyed" is emitted for QObjects but not
> for QWidgets. Any idea why?
>
> Some contest: I'm trying to construct a smarter weakref which works for
> QObject the way it should work: it becomes invalid when the QObject dies
> (and not only if the QObject's Python wrapper dies). If anybody has
> suggestions to achieve this, that'd be pretty. My idea was to use the
> destroyed() signal to find out when the QObject was destroyed and
> invalidate the reference.

I think this is the way Qt works when the receiver is a child of the sender. 
When PyQt3 makes a connection to a Python callable it creates a proxy QObject 
that is actually connected to the sender. To make sure the proxy doesn't leak 
memory it is made a child of the sender.

If I write a C++ program similar to your test where the receiver is a child of 
the sender then it behaves in the same way.

If I modify the C++ program so that the receiver is not a child of the sender, 
but instead also connects to the sender's destroyed() signal so that it can 
call deleteLater() on itself - then it seems to behave as you were expecting.

I'll probably make a change in the next snapshot or so.

Phil




More information about the PyQt mailing list