Connecting signals and slots
If you have worked with pointers in C++ or object references
in other languages, then you will probably have been wondering
whether creating signal/slot connections also means creating
object references. Remember, object A can register interest in
some signals Object B emits.
This means that somewhere there must be code that object B
calls when it wants to emit that signal; and that there must be
code that is called to notify object A. In order for that to be
possible, a reference must be stored to object A. This is known
as the observer pattern:
Example 9-9. sigslot.py - a simple signals/slots implementation
in Python, following the Observer pattern
#
# sigslot.py - a simple signals/slots implementation in Python
#
class ClassA:
def __init__(self):
self.interestedObjects=[]
def connect(self, obj):
self.interestedObjects.append(obj)
def sendSignal(self):
for obj in self.interestedObjects:
obj.slot("This is a signal from ClassA")
class ClassB:
def slot(self, message):
print "Object with ID", id(self), "Got signal: message"
objectA=ClassA()
objectB=ClassB()
objectA.connect(objectB)
objectC=ClassB()
objectA.connect(objectC)
objectD=ClassB()
objectA.connect(objectD)
objectA.sendSignal()
In this exceedingly simplified
implementation of the signals and slots concept, objectA
actually stores the references to interested objects. If the
PyQt signals and slots mechanism were implemented like this,
objects would not be deleted unless the all objects they had
connections to were deleted as well. This puts a burden on the
programmer, who would have to remember to sever all connections
by hand. We all know what happens when a programmer has to
remember cleaning up after him...
Fortunately, the implementation of signals
and slots in sip is not quite so basic. Sip works together with
the signals and slots implementation in Qt, which is highly
complex, and involves fooling around with a special-purpose
macro processor. This, at least, Python developers are
spared.
Sip keeps special proxy objects around to
handle the signal/slot connections. If you use a recent version
of Python (>2.1), the actual connections will not need real
references, but can work with the new-fangled weak reference
concept. Weak references are references that don't count for the
purpose of reference counting.
This is good, because your application will
not crash if a signal is emitted that was connected to a slot in
a deleted object — and created connections will not keep
objects alive.
Chapter 7 deals with signals and
slots in far more depth.