【问题标题】:PyQt: Consolidating signals to a single slotPyQt:将信号合并到单个插槽
【发布时间】:2010-11-07 00:24:11
【问题描述】:

我正在尝试减少我必须在上下文菜单中使用的信号量。菜单由切换程序操作模式的动作组成,因此插槽进行的操作非常简单。引用 QMenu::triggered 上的文档,

通常,您将每个菜单操作的trigger() 信号连接到其自己的自定义槽,但有时您可能希望将多个操作连接到单个槽,例如,当您有一组密切相关的操作时,例如“左对齐”、“居中”、“右对齐”。

但是,我不知道如何做到这一点,文档也没有详细说明。
假设我在菜单actionMenu 中有操作actionOpMode1actionOpMode2,以及一个插槽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() 时我可能做错了。

它是怎么做的?

【问题讨论】:

    标签: python qt


    【解决方案1】:

    使用 QObject.Sender 是一种解决方案,虽然不是最干净的。

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

    【讨论】:

    • +1,QSignalMapper 完全为此目的而设计(我认为也非常优雅),因此它提供了架构解决方案。
    【解决方案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')
    

    【讨论】:

      【解决方案3】:

      您可以使用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":
              # ...
      

      就我个人而言,第一种方法看起来更干净,更易读。

      【讨论】:

      • connect() 不会增加接收者的引用计数;除非您持有额外的引用,否则您不能在连接中使用 lambda。
      猜你喜欢
      • 2012-07-13
      • 2011-08-16
      • 2011-11-23
      • 2011-08-08
      • 2010-10-30
      • 2018-09-23
      • 2020-09-21
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多