如何制作通用的PySide单发槽

时间:2013-01-09 12:18:00

标签: python pyside

我正在尝试编写通用单镜头插件包。这就是我现在所拥有的:

def single_shot_connect(signal, slot):
  signaled = [False]
  def single_shot_slot(*args, **kwargs):
    if signaled[0]: return
    signaled[0] = True
    signal.disconnect(single_shot_slot)
    slot(*args, **kwargs)

  signal.connect(single_shot_slot)

def foo(): pass

class Bar(QtCore.QObject): sig = QtCore.Signal([int])

bar1 = Bar()
bar1.sig.connect(foo)
bar1.sig.emit(1)  # (1)

bar2 = Bar()
single_shot_connect(bar2.sig, foo)
bar2.sig.emit(1)  # (2)

问题是标记为(2)的代码无效,因为它在foo()正常工作时尝试使用一个参数调用(1)

如何让single_shot_connect()工作?

编辑: single_shot_connect()可针对此特殊情况修复,如下所示:

def single_shot_connect(signal, slot):
  signaled = [False]
  def single_shot_slot(): # Note absence of *args, **kwargs
    if signaled[0]: return
    signaled[0] = True
    signal.disconnect(single_shot_slot)
    slot() # Note absence of *args, **kwargs

  signal.connect(single_shot_slot)

但这在我的案例中并不有趣,因为我希望single_shot_connect()是通用的,可用于任何类型的信号和插槽。

1 个答案:

答案 0 :(得分:3)

由于Qt guarantees调用的插槽顺序将是connect语句的顺序,您只需执行此操作:

def single_shot_connect(signal, slot):
    def disconnect(*args, **kwargs):
        signal.disconnect(slot)
        signal.disconnect(disconnect)
    signal.connect(slot)
    signal.connect(disconnect)

发出signal后,将调用slot。之后是disconnect调用,删除slot及其自身。所以他们不会被要求随后发出。

完整用法示例:

import sys
from PySide import QtCore

class Foo(QtCore.QObject):
    sig = QtCore.Signal(int)

def bar():
    print 'running bar'


def single_shot_connect(signal, slot):
    def disconnect(*args, **kwargs):
        signal.disconnect(slot)
        signal.disconnect(disconnect)
    signal.connect(slot)
    signal.connect(disconnect)



if __name__ == '__main__':
    app = QtCore.QCoreApplication(sys.argv)

    foo = Foo()
    single_shot_connect(foo.sig, bar)

    foo.sig.emit(1)
    foo.sig.emit(2)

    QtCore.QTimer.singleShot(1000, app.exit)

    sys.exit(app.exec_())