【问题标题】:Qt: Connecting multiple input widgets with valueChanged(int) signals to single slot?Qt:将带有 valueChanged(int) 信号的多个输入小部件连接到单个插槽?
【发布时间】:2014-07-02 23:07:26
【问题描述】:

使用Qt 4.8,我以编程方式创建了许多输入小部件(QSpinBoxQSlider)。 最后,我希望有一个方法来处理任何这些输入小部件的更改,最好是通过索引。

但是,这些小部件只有一个带参数的信号,例如valueChanged(int)这与QSignalMapper() 的插槽map() 不兼容。

正如 cmets 中指出的那样,连接确实有效!

    connect(    spinbox,        SIGNAL( valueChanged(int)  ),
                signalMapper,   SLOT(   map()            )
                );

现在我只需要获取值,但这不能再通过 sender() 方法完成,因为现在是 SignalMapper。


原始问题:

除了(重新)使用附加参数实现QSignalMapper 或为小部件使用无参数valueChanged() 或使用objectNameQObject::sender() 以使插槽查看哪个元素更改(和获取新值)?

【问题讨论】:

  • 你不能只在监听映射器的槽中查询新值吗(你可以用比槽需要更多的参数发出信号)
  • 你不需要重新实现QSignalMapper。只需创建QSignalMapper 的实例并为其定义映射。它支持各种数据类型的映射,因此您可以定义整数、字符串,甚至任何转换为​​QObject* 的东西。您还希望在广告位中提供哪些其他信息?
  • 请参阅:stackoverflow.com/questions/24260394/how-works-qsignalmapper,了解如何正确使用QSignalMapper。这确实是您需要做的最好的解决方案。
  • @Googie 是的,我不介意使用 QSignalMapper,但是我的小部件没有与您发布的示例解决方案中使用的 clicked() 方法等效的方法。或者我还是不明白 - 你能在答案中发布一个例子吗?

标签: c++ qt signals-slots


【解决方案1】:

您可以使用QAbstractSpinBox::editingFinished()QAbstractSlider::sliderReleased() 作为您的信号,它们是无参数的。

不幸的是,QAbstractSlider::valueChanged() 没有无参数版本,因此如果您希望在滑块移动时连续发出信号,您可能需要继承 QSlider 并创建它。例如

class MySlider : public QSlider
{
   ...
   private slots:
      void HandleValueChanged(int) { emit valueChanged(); }
   signals:
      void valueChanged();
};

MySlider::MySlider(...)
{
    connect(this, SIGNAL(valueChanged(int)), this, SLOT(HandleValueChanged(int)));
}

虽然我承认,这可能不是最优雅的解决方案。

【讨论】:

  • 这并不能解决这里的主要问题 - 将发行者的索引传递给插槽。
  • 是的,但是你可以将 QObject::sender() 投射到正确的对象上,并询问它是 currentIndex() (它很难看)。
  • @Googie 不是吗? QSignalMapper 创建索引的等价物,这就是它的用途。它只需要一个无参数的信号。
  • @MattPhillips 是的,但是如果我正确理解了这个问题,@handle 会询问除了QObject::sender()QSignalMapper 是否还有其他方法。事实是QSignalMapper 最适合这个,这就是我在他的询问下的评论中建议他的。我真的不明白他为什么要寻找其他解决方案 - 也许他以错误的方式使用 QSignalMapper
  • @Googie 好的,严格按照字面理解 OP 的问题,你是对的,但我认为他/她会满意地发现 QSignalMapper 毕竟有效——正如你试图展示的那样你的cmets。所以我认为我们的波长相同。
【解决方案2】:

如果我正确理解了您的问题以及您到目前为止所拥有的内容,那么您缺少两个部分。

mapper->setMapping(<spinbox>, <id or name or pointer to the spinbox);
connect(mapper, SIGNAL(mapped(<datatype you used in setMapping()>),
this, SLOT(HandleValueChanged(<datatype you used in setMapping()>)));

所以HandleValueChanged() 插槽将接收到您的发送者的标识符,然后您可以使用适当的 getter 直接访问发送者的值。 方法setMapping() 将整数、QString 或指向小部件本身的指针作为第二个参数。然后通过映射器的 mapped() 信号转发此信号,以便您稍后识别哪个小部件发出了信号。

【讨论】:

  • 是的,然后可以像int n = qobject_cast&lt;QSpinBox*&gt;(widget)-&gt;value(); 一样访问数据,类似于使用 sender() 的直接连接,但这也不提供索引。但是, 可以以某种方式映射到 ..
  • 抱歉,我不明白您的问题/评论。 “不提供索引”是什么意思?你想要什么样的索引?通常,在为每个要捕获更改的小部件调用 setMapping() 方法时,您自己为每个小部件选择一个索引。
  • 索引我的意思是你所说的id。我想要小部件值和 id,但 QSignalMapper 只能做任何一个。但是有很多方法。感谢您的意见!
猜你喜欢
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 2016-03-20
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多