<div dir="ltr"><div style="font-size:12.8000001907349px">Hi,</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I am using PyQt4 4.10.4.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I'm a bit puzzled by the pyqtSlot decorator. All I can find in the docs is that it potentially</div><div style="font-size:12.8000001907349px">improves performance, but I'm witnessing actual different behaviour depending on how I use it.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">1.  The decorator seems to properly disconnect slots when the object is deleted.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">    In the snippet below, a slot of a widget to be deleted is connected to a button's click.</div><div style="font-size:12.8000001907349px">    If I close the SlotWidget and click the button, without the decorator I get a:</div><div style="font-size:12.8000001907349px">        "RuntimeError: wrapped C/C++ object of type QLabel has been deleted".</div><div style="font-size:12.8000001907349px">    With the decorator, the signal is disconnected before the object is destroyed and the click</div><div style="font-size:12.8000001907349px">    has no effect.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">    My conclusion thus is that it's quite important to decorate slots like this.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        from PyQt4 import QtGui, QtCore</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        app = QtGui.QApplication([])</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        class SlotWidget(QtGui.QWidget):</div><div style="font-size:12.8000001907349px">            def __init__(self, parent=None):</div><div style="font-size:12.8000001907349px">                QtGui.QWidget.__init__(self, parent)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">                self.label = QtGui.QLabel('LABEL', parent=self)</div><div style="font-size:12.8000001907349px">                # Make sure the object is deleted so potential problems arise</div><div style="font-size:12.8000001907349px">                self.setAttribute(QtCore.Qt.WA_DeleteOnClose)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            # Without this decorator, when this widget is closed and the button is</div><div style="font-size:12.8000001907349px">            # clicked, you get a RuntimeError.</div><div style="font-size:12.8000001907349px">            @QtCore.pyqtSlot()</div><div style="font-size:12.8000001907349px">            def my_slot(self):</div><div style="font-size:12.8000001907349px">                print 'Label text: %s' % self.label.text()</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        class MyWidget(QtGui.QWidget):</div><div style="font-size:12.8000001907349px">            def __init__(self, parent=None):</div><div style="font-size:12.8000001907349px">                QtGui.QWidget.__init__(self, parent)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">                self.button = QtGui.QPushButton("Button", parent=self)</div><div style="font-size:12.8000001907349px">                self.slot_widget = SlotWidget(parent=None)</div><div style="font-size:12.8000001907349px">                self.slot_widget.show()</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">                self.button.clicked.connect(self.slot_widget.my_slot)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        if __name__ == "__main__":</div><div style="font-size:12.8000001907349px">            widget = MyWidget()</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            widget.show()</div><div style="font-size:12.8000001907349px">            app.exec_()</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">2.  Consider this mock example; here, I want to provide some base functionality for my widgets,</div><div style="font-size:12.8000001907349px">    that involves connecting a signal to a slot. I don't want to inherit from QObject since multiple</div><div style="font-size:12.8000001907349px">    inheritance from QObject creates all sorts of issues in PyQt4.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">    What I notice is that decorating the slot leads to an error:</div><div style="font-size:12.8000001907349px">        "TypeError: connect() failed between timeout() and base_slot()".</div><div style="font-size:12.8000001907349px">    Even weirder, calling the Base constructor before the QWidget one ensures that the slot</div><div style="font-size:12.8000001907349px">    is called properly.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">    So in this case it seems to be better not to decorate the slot, but it can lead to problems (see 1.).</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        from PyQt4 import QtGui, QtCore</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        app = QtGui.QApplication([])</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        class Base(object):</div><div style="font-size:12.8000001907349px">            def __init__(self, timer):</div><div style="font-size:12.8000001907349px">                self.timer = timer</div><div style="font-size:12.8000001907349px">                self.timer.timeout.connect(self.base_slot)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            # Remove the decorator -> works regardless of __init__ order</div><div style="font-size:12.8000001907349px">            @QtCore.pyqtSlot()</div><div style="font-size:12.8000001907349px">            def base_slot(self):</div><div style="font-size:12.8000001907349px">                print 'Fired!'</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        class MyWidget(QtGui.QWidget, Base):</div><div style="font-size:12.8000001907349px">            def __init__(self, timer, parent=None):</div><div style="font-size:12.8000001907349px">                # Switch the order -> works regardless of decorator</div><div style="font-size:12.8000001907349px">                QtGui.QWidget.__init__(self, parent)</div><div style="font-size:12.8000001907349px">                Base.__init__(self, timer)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">                self.button = QtGui.QPushButton("Button", parent=self)</div><div style="font-size:12.8000001907349px">                self.button.clicked.connect(self.derived_slot)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            @QtCore.pyqtSlot()</div><div style="font-size:12.8000001907349px">            def derived_slot(self):</div><div style="font-size:12.8000001907349px">                print 'Preparing to fire...'</div><div style="font-size:12.8000001907349px">                self.timer.start(2000)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">        if __name__ == "__main__":</div><div style="font-size:12.8000001907349px">            timer = QtCore.QTimer()</div><div style="font-size:12.8000001907349px">            timer.setSingleShot(True)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            widget = MyWidget(timer)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">            widget.show()</div><div style="font-size:12.8000001907349px">            app.exec_()</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">3.  Are slots always supposed to be bound? (i.e., should all the slots have a self first argument?)</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">4.  I would expect that explicitly decorating the slot with (C++) types should provide enough</div><div style="font-size:12.8000001907349px">    information to disambiguate between overloaded signals. E.g., if I have a slot decorated with</div><div style="font-size:12.8000001907349px">    @QtCore.pyqtSlot(str) and connect it to QComboBox.activated it connects to the int signal</div><div style="font-size:12.8000001907349px">    by default (I have to connect to QComboBox.activated[str]).</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">I didn't come up with this stuff for the fun of it, all these issues were raised as they caused</div><div style="font-size:12.8000001907349px">serious problems in my code (e.g., obscure segfaults). Any explanations would be greatly welcome.</div><div style="font-size:12.8000001907349px"><br></div><div style="font-size:12.8000001907349px">Thanks,</div><div style="font-size:12.8000001907349px">Iosif</div></div>