2

一般的なシングル ショット スロット ラッパーをコーディングしようとしています。これが私が今持っているものです:

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)

問題は、マークされたコードが正しく機能しているときに 1 つの引数で(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()汎用的で、あらゆる種類の信号とスロットで使用できるようにしたいからです。

4

1 に答える 1

3

Qtは、呼び出されるスロットの順序がステートメントの順序になることを保証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呼び出されます。その後に、 and 自体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_())
于 2013-01-10T05:33:48.420 に答える