[PyQt] Weird behaviour of destroyed() slots

Phil Thompson phil at riverbankcomputing.com
Sat Jul 26 23:31:33 BST 2008


On Sat, 26 Jul 2008 21:07:09 +0200, Giovanni Bajo <rasky at develer.com>
wrote:
> On Sat, 2008-07-26 at 17:10 +0100, Phil Thompson wrote:
>> On Wed, 23 Jul 2008 15:42:18 +0200, Giovanni Bajo <rasky at develer.com>
>> wrote:
>> > Hi Phil:
>> > 
>> >
>>
>
=============================================================================
>> > import sip
>> > from PyQt4.Qt import *
>> > 
>> > called = []
>> > 
>> > class Core(QObject):
>> >      def __init__(self, parent=None):
>> >          QWidget.__init__(self, parent)
>> >          QObject.connect(self, SIGNAL("destroyed()"), self.callback)
>> >          QObject.connect(self, SIGNAL("destroyed()"), lambda: 
>> > self.callback())
>> >      def callback(self):
>> >          called.append("done")
>> > 
>> > app = QApplication([])
>> > core = Core(app)
>> > sip.delete(core)
>> > 
>> > assert len(called) == 2, called
>> >
>>
>
=============================================================================
>> > Traceback (most recent call last):
>> >    File "bugpyqt.py", line 18, in <module>
>> >      assert len(called) == 2, called
>> > AssertionError: ['done']
>> > 
>> > The slot with "lambda" is called, but the other one is not.
>> 
>> The reason is that PyQt knows that self is being destroyed and
>> self.callback may be a wrapped C++ method (although it isn't in this
> case)
>> so it won't invoke it.
> 
> Why does it refuse to invoke a wrapped C++ method? Even if self is being
> destroyed (that is: within its C++ destructor) is still valid to invoke
> methods AFAICT. After all, it's something that's perfectly doable in C++
> as well. Or not?

I had second thoughts after my first response. A wrapped C++ method will
check to see if the C++ instance has been destroyed anyway, so there is no
need to check it here as well.

However, a wrapped C++ method still won't work in exactly the same way as a
C++ application because the "C++ instance has been destroyed" flag has to
be set before the destroyed() signal has been emitted. But it's ok for pure
Python methods.

Phil



More information about the PyQt mailing list