我们如何将值传递给此QT代码中的GUI的所有元素

时间:2016-06-27 18:43:12

标签: c++ qt

我正在读一本关于QT4的书,这是本书的一个例子:

QApplication a(argc, argv); 
QWidget window;

QVBoxLayout* mainLayout = new QVBoxLayout(&window);

QLabel* label = new QLabel("0");
QSpinBox* spinBox = new QSpinBox;
QSlider* slider = new QSlider(Qt::Horizontal);

mainLayout->addWidget(label);
mainLayout->addWidget(spinBox);
mainLayout->addWidget(slider);

QObject::connect(spinBox, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)));
QObject::connect(spinBox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
QObject::connect(slider, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)));
QObject::connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));

window.show();

正如本书和编辑所示,更改其中一个小部件的值会导致更改其他元素的值。

我不明白是怎么回事。我们如何将这个值从一个小部件传递给其他小部件?没有变量可以通过一个小部件进行更改并传递给其他小部件。

PS从概念上讲,我确实理解了插槽和信号以及“连接”的概念。这是值从一个小部件传递到其余小部件的方式是问题。

1 个答案:

答案 0 :(得分:1)

信号是一种C ++方法,其代码由名为moc的实用程序(元对象编译器)生成。插槽是常规的C ++方法,代码在您的控制之下。连接是一种让信号知道要调用的插槽的方法。当信号被发出时,它实际上意味着你调用迭代连接列表的机器生成的方法。

从概念上讲,valueChanged信号实现如下所示:

void valueChanged(int value) {
  for (slot : this->slots)
    (slot.object->*slot.method)(value);
}

因此,当滑块“发出”其信号时,它会调用具有给定值的每个插槽。建立连接后,您应该将spinbox的valueChanged信号视为执行以下操作:

void SpinBox::valueChanged(int value) {
  // 1st connection
  label->setNum(value);
  // 2nd connection
  slider->setVale(value);
}

没有“变量”被改变,因为信号槽机制的核心是一种更容易使用的方法来进行间接方法调用(通过方法指针和实例指针)。

在现代代码(Qt5 / C ++ 11)中,该示例将是(这是完整的代码):

#include <QtWidgets>

int main(int argc, char** argv) {
   QApplication a{argc, argv};
   QWidget window;

   QVBoxLayout mainLayout{&window};

   QLabel label{"0"};
   QSpinBox spinBox;
   QSlider slider{Qt::Horizontal};

   mainLayout.addWidget(&label);
   mainLayout.addWidget(&spinBox);
   mainLayout.addWidget(&slider);

   QObject::connect(&spinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
                    &label, static_cast<void(QLabel::*)(int)>(&QLabel::setNum));
   QObject::connect(&spinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
                    &slider, static_cast<void(QSlider::*)(int)>(&QSlider::setValue));
   QObject::connect(&slider, static_cast<void(QSlider::*)(int)>(&QSlider::valueChanged),
                    &label, static_cast<void(QLabel::*)(int)>(&QLabel::setNum));
   QObject::connect(&slider, &QSlider::valueChanged, &spinBox, &QSpinBox::setValue);

   window.show();
   return a.exec();
}