使用Qt信号和插槽直接调用方法

时间:2014-02-19 23:56:51

标签: c++ qt user-interface class-design signals-slots

假设我有一个带有滑块的主窗口和该窗口内的窗口小部件,其方法名为setValue(int)。每次滑块的值发生变化时,我都想调用此方法。

以下两种实现方式之间是否存在实际差异:

1

void MainWindow::on_slider_valueChanged(int value)
{
    ui->widget->setValue(value);
}

2

// somewhere in constructor
connect(ui->slider, SIGNAL(valueChanged(int)), ui->widget, SLOT(setValue(int)));

对我来说,第一种方法看起来更好,因为它可能避免了与信号和插槽机制相关的一些开销,并允许我在发送value之前处理widget,如果有需要的话为了它。

是否存在第二种解决方案更好的情况?

5 个答案:

答案 0 :(得分:9)

两种方法都使用信号槽连接。在第一种情况下,connect来自QMetaObject::connectSlotsByName()的{​​{1}}来电。在第二种情况下,您自己明确地呼叫setupUi

此外,在使用C ++ 11时,Qt5中不需要第一种方法。您可以修改lambda中的值:

connect

为了防止删除QObject::connect(ui->slider, &QAbstractSlider::valueChanged, [this](int val){ ui->widget->setValue(val*2); }); ,您应该使用ui->widget

QPointer

信号槽连接的开销是quantified in this answer

答案 1 :(得分:4)

信号/插槽优势:

  • 多个插槽可以连接到单个信号,你不必为此分配和释放内存而烦恼
  • 您可以使用此
  • 处理多线程

信号/插槽缺点:

  • 比直接呼叫慢一点
  • 如果插槽是虚拟的话,
  • 明显变慢
  • QObject相当重要,所以你通常会尽量避免构建数十亿个

有更多详情可供here

答案 2 :(得分:1)

在您的示例中,使用信号而不是直接调用的主要区别是允许多个侦听器。

如果你直接调用你的widget setValue(),那么只有那个小部件会收到C ++信号。

如果您使用Qt信号,现在任何其他对象都可以连接以在事件发生时接收该事件。

如果你没有预见到任何其他物体想要通过信号接收价值,我不会打扰这样的。直接调用肯定要快得多(在3到6个CPU指令之间,而不是处理字符串以找到接收器!),但正如Paranaix所提到的,在GUI中它可能不是一个大问题(尽管在这种情况下它可能会成为如果在移动滑块时发送所有这些信号,则旧计算机出现问题。)

答案 3 :(得分:1)

我更喜欢第二种方法,因为在删除UI元素时忘记删除“自动连接槽”,导致死代码。 AFAIK它与“幕后”相同(查看自动生成的qt文件)。

如果您想修改该值,我更愿意遵循以下方法:

connect(ui->slider, SIGNAL(valueChanged(int)), this, SLOT(myOwnSlot(int)));

void MainWindow::myOwnSlot(int value) {
    /** do stuff */
    ui->widget->setValue(value);
}

格尔茨

答案 4 :(得分:0)

信号&插槽是一种不同的编码风格。你可以使用有用的信号做一些事情,并且可以很好地解决传统的c ++问题。例如,您可以从const函数发出const信号,并将它们连接到非const槽(在c ++中,您不能从const函数进行非const调用)。我从来不喜欢使用可变对象,所以信号为我提供了一个干净的工作。