Using Qt signals and slots vs calling a method directly

jaho picture jaho · Feb 20, 2014 · Viewed 8.5k times · Source

Lets say I have a main window with a slider and a widget inside that window with a method called setValue(int). I'd like to call this method every time the value of the slider has changed.

Is there any practical difference between the two following ways of achieving it:

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)));

For me the first approach looks better, because it possibly avoids some overhead related to signals and slots mechanism and also, allows me to process the value before sending it to widget, if there's a need for it.

Are there any scenarios where the second solution is better?

Answer

Both approaches use signal-slot connections. In the first case, the connect call is made by QMetaObject::connectSlotsByName() called from setupUi. In the second case, you explicitly call connect yourself.

Also, the first approach is unnecessary in Qt5 when using C++11. You can modify the value in a lambda:

QObject::connect(ui->slider, &QAbstractSlider::valueChanged,
                 [this](int val){ ui->widget->setValue(val*2); });

To protect from deletion of ui->widget, you should use a QPointer:

class MyWindow : public QMainWindow {
  QPointer<QAbstractSlider> m_widget;
  ...
public:
  MyWindow(QWidget * parent = 0) : QMainWindow(parent) {
    ...
    setupUi(this);
    m_widget = ui->widget;
    QObject::connect(ui->slider, &QAbstractSlider::valueChanged, 
                    [this](int val)
    {
      if (!m_widget.isNull()) m_widget->setValue(val*2); 
    });

The overhead of signal-slot connections is quantified in this answer.