[PyQt] chain signals, disconnecting an "emit" slot

Phil Thompson phil at riverbankcomputing.com
Tue Apr 16 11:29:05 BST 2013


On Mon, 15 Apr 2013 11:02:19 -0500, Luke Lee <durdenmisc at gmail.com> wrote:
> As mentioned here,
>
http://www.riverbankcomputing.com/pipermail/pyqt/2011-October/030578.html,
> you cannot use the 'disconnect' method to disconnect something when the
> signals were connected via the emit() method.
> 
> I'm curious about the details of why connecting signals to the emit()
> method does not work.  I've tried to do some debugging myself, but I'm
> still a bit confused.
> 
> It looks as though the pyqtSignal object **changes** during the course
of a
> running application.  For example, consider the following line:
> 
> ok.pressed.connect(cancel.pressed.emit)
> 
> As previously mentioned doing a disconnect like the following doesn't
work:
> 
> ok.pressed.disconnect(cancel.pressed.emit)
> 
> I've tried debugging by printing the id() of the cancel.pressed object
> (pyqtSignal) as well as the id() of the cancel.pressed.emit method. 
These
> object ids actually **change** between when I connect and later try to
> disconnect.
> 
> I've verified that I'm not deleting the objects, etc.  Also, calling
> cancel.pressed.emit() works as you can imagine even though it's
seemingly a
> different object than the one that was connected earlier.  What exactly
is
> happening here?
> 
> I'm assuming it has something to do with the wrapping of the C++ code
and
> maybe the QMetaObject
(http://qt-project.org/doc/qt-4.8/qmetaobject.html)
> is involved somehow.
> 
> I'm really just trying to understand why these ids don't match up and
why
> connecting signals to signals is preferred vs. connecting to the emit
> method.  I can easily change my code to connect the signals via the
> preferred method, but I felt like there was a useful lesson to learn
here.
>  Thoughts?

Signals work in a similar way to class methods. A signal object is an
attribute of a class, not an attribute of an instance of the class. When
you refer to a signal as an instance attribute a bound signal object is
automatically created and returned. Normally this will then be garbage
collected as soon as it is used. The pyqtSignal object doesn't change,
instead you are seeing different pyqtBoundSignal objects. Unbound and bound
methods work in the same way.

Connecting to emit doesn't work because of the transitory nature of
pyqtBoundSignal objects. Connecting to bound methods does work because SIP
has explicit support for it - SIP doesn't known anything about new-style
signals.

I could "fix" this, but I'm not going to. Connecting signals to signals is
the Qt way of doing things and is much more efficient.

Phil


More information about the PyQt mailing list