[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