PyQt:将信号整合到一个插槽中

时间:2009-06-30 13:36:19

标签: python qt

我试图减少我在上下文中使用的信号量。菜单包括切换程序操作模式的动作,因此插槽执行的操作非常简单。引用QMenu :: triggered,

上的文档
  

通常,您将每个菜单操作的triggered()信号连接到其自己的自定义插槽,但有时您需要将多个操作连接到单个插槽,例如,当您有一组密切相关的操作时,例如“左对齐“,”中心“,”右对齐“。

但是,我无法弄清楚如何实现这一点,文档没有进一步详细说明 假设我在菜单actionOpMode1中有actionOpMode2actionMenu,以及一个广告符setOpMode。我希望用一个参数来调用setOpMode,该参数在某种程度上与触发了哪些动作有关。我尝试了这个主题的各种排列:

    QObject.connect(self.actionMenu, SIGNAL('triggered(QAction)'), self.setOpMode)  

但是我从来没有得到它来调用setOpMode,这表明actionMenu永远不会“感觉被触发”,可以这么说。

this SO question中,建议可以使用lamdbas完成,但是这样:

    QObject.connect(self.actionOpMode1, SIGNAL('triggered()'), lambda t: self.setOpMode(t))

给出"<lambda> () takes exactly 1 argument (0 given)"。我不能说我真的明白这是怎么回事,所以从clicked()转到trigger()时我可能做错了。

怎么做?

3 个答案:

答案 0 :(得分:4)

使用QObject.Sender是解决方案之一,尽管不是最干净的解决方案。

使用QSignalMapper将值与发出信号的对象完全关联。

答案 1 :(得分:2)

我使用这种方法:

from functools import partial

def bind(self, action, *params):
    self.connect(action, QtCore.SIGNAL('triggered()'), 
                 partial(action, *params, self.onMenuAction))

def onMenuAction(self, *args):
    pass


bind(self.actionOpMode1, 'action1')
bind(self.actionOpMode2, 'action2')

答案 2 :(得分:1)

您可以使用QObject::sender()来确定发出信号的QAction。

所以你的插槽可能如下所示:

def triggered(self):
    sender = QtCore.QObject.sender()

    if sender == self.actionOpMode1:
        # do something
    elif sender == self.actionOpMode2:
        # do something else

关于你在lambda中提到的另一个SO问题中发生了什么,它所做的是创建一个带有一个参数的lambda,该参数具有默认值,因此要将其应用于您的示例,您需要执行以下操作:

self.connect(self.actionOpMode1, QtCore.SIGNAL('triggered()'), lambda who="mode1": self.changeMode(who))
self.connect(self.actionOpMode2, QtCore.SIGNAL('triggered()'), lambda who="mode2": self.changeMode(who))

然后有一个像这样的成员函数:

def changeMode(self, who):
    if who == "mode1":
        # ...
    elif who == "mode2":
        # ...

就个人而言,第一种方法看起来更清晰,更易读。