关于python:pyqt断开插槽。 新风格

pyqt disconnect slots. New style

我为此分配一个插槽。

1
2
3
4
5
...
self.query = QtGui.QLineEdit(self)            
self.query.textChanged.connect(lambda: self.makeThread(self.googleSearch()))
self.query.returnPressed.connect(lambda: self.launchNavigator(1))
...

但是如何断开连接? 我尝试过此操作,但不起作用...

1
2
self.query.textChanged.disconnect(lambda: self.makeThread(self.googleSearch()))
self.query.returnPressed.disconnect(lambda: self.launchNavigator(1))

lambda表达式返回不同的函数(或多或少是偶然的;))将执行相同的操作。因此,您将信号连接到的信号与尝试断开信号时使用的第二个lambda信号不同。看这个例子:

1
2
3
4
>>> f = lambda x: x
>>> g = lambda x: x
>>> f is g
False

您可以使用不带任何参数的self.query.textChanged.disconnect(),这将使信号与所有插槽断开连接(如果只有一个连接,可能没问题),或者必须将对lambda的引用存储在某个位置:

1
2
3
4
self.func1 = lambda: self.makeThread(self.googleSearch())
self.query.textChanged.connect(self.func1)
...
self.query.textChanged.disconnect(self.func1)


有一种绝妙的方法,可以使用原始连接返回的QConnection对象断开信号。所以:

1
2
self.conn1 = self.query.textChanged.connect(lambda: self.makeThread(self.googleSearch()))
self.conn2 = self.query.returnPressed.connect(lambda: self.launchNavigator(1))

然后随后:

1
2
self.disconnect(self.conn1)
self.disconnect(self.conn2)

尽管此功能在Qt中已经存在很长时间了,但在PyQt 5.13.1之前并未实现。


我想在有关绑定方法的@rainer答案中添加一个警告/扩展。请记住,将方法绑定到实例(例如,通过编写self.slotname)实际上每次都会创建一个新的闭包(如本问题所述)。

因此,您在做同样的问题

1
2
3
4
5
6
7
8
9
10
def test_slot(self):
    self.makeThread(self.googleSearch())

...

    self.query.textChanged.connect(self.test_slot)

...

    self.query.textChanged.disconnect(self.test_slot)

就像您对问题中的原始lambda所做的那样。解决方案是将闭包self.test_slot存储在属性中,如@rainer所建议。这是必要的,因为每次您在代码中写入self.test_slot时,都会生成一个大致等同于lambda: type(self).test_slot(self)的新对象。只要您准确地进行簿记,以下内容就可以正常工作:

1
2
3
4
5
6
    self.func = self.test_slot
    self.query.textChanged.connect(self.func)

...

    self.query.textChanged.disconnect(self.func)