我正在尝试编写通用单镜头插件包。这就是我现在所拥有的:
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()
是通用的,可用于任何类型的信号和插槽。
答案 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_())