On Tue, 15 May 2012 17:34:05 +0300, Alexander Bruy <alexander.b...@gmail.com> wrote: > Hi all, > > I try to use new style for signal-slot connection [0] in my project. And > have one problem that looks like bug in PyQt. > > There is a dialog window with QDialogButtonBox, which has two buttons > OK and Close. During the program execution I need to change behavior > of Close button: pressing this button should not close the dialog but > invoke > another slot. Using old signal-slot connection I implement this as > > self.btnClose = self.buttonBox.button( QDialogButtonBox.Close ) > # disconnect from rejected() slot > QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.reject ) > # and connect to user-defined slot > QObject.connect( self.btnClose, SIGNAL( "clicked()" ), self.stopProcessing > ) > .... > # restore original state > QObject.disconnect( self.btnClose, SIGNAL( "clicked()" ), > self.stopProcessing ) > QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.reject ) > > And all works fine as I want. But when i use new style for signal-slot > connection > in same code > > self.btnClose = self.buttonBox.button( QDialogButtonBox.Close ) > self.buttonBox.rejected.disconnect( self.reject ) > self.btnClose.clicked.connect( self.stopProcessing ) > ... > self.btnClose.clicked.disconnect( self.stopProcessing ) > self.buttonBox.rejected.connect( self.reject ) > > I get error in run-time > > line 147, in prepareProcess > self.buttonBox.rejected.disconnect( self.reject ) > TypeError: disconnect() failed between ‘rejected’ and ‘reject’ > > Dialog designed in QtDesigner and compiled to Python code using > pyuic4. > > After some investigating I found that pyuic4 generates code using > old-style signal-slot connections > > QtCore.QObject.connect(self.buttonBox, > QtCore.SIGNAL(_fromUtf8("accepted()")), Dialog.accept) > QtCore.QObject.connect(self.buttonBox, > QtCore.SIGNAL(_fromUtf8("rejected()")), Dialog.reject) > > If I replace this string in generated file with new style connections > > self.buttonBox.accepted.connect(Dialog.accept) > self.buttonBox.rejected.connect(Dialog.reject) > > my code again works fine. This was tested under Linux: with > Python 2.6.6, Qt 4.7.0 and PyQt 4.8.1. And under Windows using > - Python 2.7.3, PyQt 4.9, Qt 4.8.0 > - Python 3.2.2, PyQt 4.9.1, Qt 4.8.0. > > I think that incompatibility between new and old style for signal-slot > connections is a major bug that can cause many problems when UI > created in Designer and some signals and slots should be connected > and disconnected in run-time. > > I create simple demo for this bug, find it attached. > > [0] > http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/new_style_signals_slots.html > > Thanks and sorry for my English
This is what's happening... PyQt allows connections to be made to any Python callable. With old style connections a proxy slot is created under the covers whenever a callable is used (as opposed to when SLOT() is used to refer to a C++ slot). Therefore, in your example, a proxy is always created for the connection to Dialog.reject even though that refers to the object that wraps the C++ slot (as there is no Python reimplementation of reject()). New style connections are a bit smarter in that they treat slot objects that refer to a wrapped C++ slot and objects that refer to some real Python code differently - a proxy is only created in the latter case. A possible workaround might be to add a null implementation of reject() to the BugDemo class... def reject(self): super(BugDemo, self).reject() ...which would force new style connections to create a proxy - and for disconnect() to assume that a proxy was being used. So the rule is that if you make a connection old style then you must disconnect old style as well and the same for new style. You also need to be aware that pyuic4 uses old style connections. I accept that this is a bug, but I don't want to fix it. The reason is that the changes required to the old style support code would be quite significant and I don't think the risk to the stability of that code is worth it at this stage of the life of PyQt4, particularly as the workaround is straightforward. This bug has been present for 3 years and it's the first time I remember it being reported. Obviously I will update the documentation. Phil _______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt