PyQt断开槽函数。新风格

8
我用以下代码来指定插槽:

使用以下代码指定插槽:

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

但是我该如何断开连接呢?我尝试了这个方法,但它并没有起作用...

self.query.textChanged.disconnect(lambda: self.makeThread(self.googleSearch()))
self.query.returnPressed.disconnect(lambda: self.launchNavigator(1))
3个回答

15

lambda表达式会返回不同的函数(多少有点巧合),它们会完成相同的事情。因此,你所连接的信号与你尝试断开它时使用的第二个lambda并不是同一个东西。请参考以下示例:

>>> f = lambda x: x
>>> g = lambda x: x
>>> f is g
False

你可以使用 self.query.textChanged.disconnect(),不带参数进行断开连接,这将从所有插槽中断开信号(如果您只有该一个连接,则可能没问题),或者您需要在某个地方存储lambda的引用:

self.func1 = lambda: self.makeThread(self.googleSearch())
self.query.textChanged.connect(self.func1)
...
self.query.textChanged.disconnect(self.func1)

你关于lambda所说的,对于functools.partial也适用吗? - Guimoute

5

使用原始连接返回的QConnection对象可以优雅地断开信号。因此:

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

之后随后:

self.disconnect(self.conn1)
self.disconnect(self.conn2)

在PyQt 5.13.1之前,这个特性尚未被实现,虽然它在Qt中已经存在了很长一段时间。


3
这个答案肯定应该被采纳,这是最简洁的方法。 - soz

1
我希望对@rainer关于绑定方法的回答进行补充/扩展。请记住,将方法绑定到实例(例如,通过编写self.slotname)实际上会每次创建一个新的闭包(如this问题中所述)。
因此,您在执行以下操作时会遇到相同的问题。
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)。只要你准确地进行簿记,以下内容将正常工作:
    self.func = self.test_slot
    self.query.textChanged.connect(self.func)

...

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接