I assign a slot with this.
...
self.query = QtGui.QLineEdit(self)
self.query.textChanged.connect(lambda: self.makeThread(self.googleSearch()))
self.query.returnPressed.connect(lambda: self.launchNavigator(1))
...
but how can I disconnect? I tried with this but it does not work...
self.query.textChanged.disconnect(lambda: self.makeThread(self.googleSearch()))
self.query.returnPressed.disconnect(lambda: self.launchNavigator(1))
The lambda expressions return different functions that (more or less by chance ;) ) will do the same thing. Therefore, what you connected your signal to is not the same thing as the second lambda you're using when trying to disconnect it; see this example:
>>> f = lambda x: x
>>> g = lambda x: x
>>> f is g
False
You can either use self.query.textChanged.disconnect()
without any parameters, which will disconnect the signal from all slots (which might be ok if you only have that one connection) or you will have to store a reference to the lambda somewhere:
self.func1 = lambda: self.makeThread(self.googleSearch())
self.query.textChanged.connect(self.func1)
...
self.query.textChanged.disconnect(self.func1)
There is an elegant way of disconnecting a signal using the QConnection object returned by the original connection. So:
self.conn1 = self.query.textChanged.connect(lambda: self.makeThread(self.googleSearch()))
self.conn2 = self.query.returnPressed.connect(lambda: self.launchNavigator(1))
And then subsequently:
self.disconnect(self.conn1)
self.disconnect(self.conn2)
This feature was not implemented prior to PyQt 5.13.1, although it has existed in Qt for a long time.
I would like to add a caveat/extension to @rainer's answer pertaining to bound methods. Keep in mind that binding a method to an instance (e.g., by writing self.slotname
) actually creates a new closure every time (as in this question).
You would therefore have the same problem doing
def test_slot(self):
self.makeThread(self.googleSearch())
...
self.query.textChanged.connect(self.test_slot)
...
self.query.textChanged.disconnect(self.test_slot)
as you did with the original lambda
in your question. The solution is to store the closure self.test_slot
in an attribute, as @rainer suggests. This is necessary because a new object that is roughly equivalent to lambda: type(self).test_slot(self)
is generated every time you write self.test_slot
in your code. The following will work fine as long as you do the book-keeping accurately:
self.func = self.test_slot
self.query.textChanged.connect(self.func)
...
self.query.textChanged.disconnect(self.func)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With