Re: [PyQt] Possible bug with new signal-slot connection
Am Donnerstag, 17. Mai 2012, 22:27:32 schrieb Hans-Peter Jansen: > On Wednesday 16 May 2012, 22:21:05 Phil Thompson wrote: > > 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. > > While all of this makes sense, it might be worthwhile to add an option > to pyuic4 that creates new style signals & slots. Plus one from my side for this suggestion. > > Pete > ___ > PyQt mailing listPyQt@riverbankcomputing.com > http://www.riverbankcomputing.com/mailman/listinfo/pyqt -- Detlev Offenbach det...@die-offenbachs.de___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Possible bug with new signal-slot connection
On Wednesday 16 May 2012, 22:21:05 Phil Thompson wrote: > > 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. While all of this makes sense, it might be worthwhile to add an option to pyuic4 that creates new style signals & slots. Pete ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Possible bug with new signal-slot connection
Hi Phil, many thanks for detailed explanation. You are right making significant changes in old code that can break compatibility or stability is no good. But it will good to add this explanation to documentation. 2012/5/16 Phil Thompson : > 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 Thanks again -- Alexander Bruy ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Possible bug with new signal-slot connection
On Tue, 15 May 2012 17:34:05 +0300, Alexander Bruy 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 listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Possible bug with new signal-slot connection
Hi Pete, thanks for answer, but I need both slots: reject() and custom slot. Also even if I reimplement reject() this incompatibility between old and new style for signal-slot connection remains. Main question is not my code but this incompatibility 2012/5/16 Hans-Peter Jansen : > Apart from your issue, consider to subclass QDialog and reimplement reject to > conditionally do what you want without continuously fiddling with > {dis,}connect. > > Pete Thansk -- Alexander Bruy ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Possible bug with new signal-slot connection
Hi Alexander, Am Tuesday 15 May 2012 16:34:05 schrieb Alexander Bruy: > 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. Apart from your issue, consider to subclass QDialog and reimplement reject to conditionally do what you want without continuously fiddling with {dis,}connect. Pete ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
[PyQt] Possible bug with new signal-slot connection
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 -- Alexander Bruy pyqt_bug.tar.bz2 Description: BZip2 compressed data ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt