The idea in this code is to set up a relationship between a QSpinBox, QProgressBar, QSlider, and a QDial. The progress bar is read only and only reacts when its value is changed. Modifying the value of the other three widgets will cause all four to be updated automatically.
#include <QtCore>
#include <QtGui>
class MainWindow : public QWidget
{
public:
MainWindow();
};
The declaration for MainWindow has not changed for this example.
MainWindow::MainWindow()
{
setMinimumSize(700, 350);
QSpinBox *spinBox = new QSpinBox;
spinBox->setMinimum(0);
spinBox->setMaximum(100);
QFont font = spinBox->font();
font.setPointSize(10);
spinBox->setFont(font);
QProgressBar *progressBar = new QProgressBar;
progressBar->setMinimum(0);
progressBar->setMaximum(100);
QSlider *slider = new QSlider;
slider->setMinimum(0);
slider->setMaximum(100);
QDial *dial = new QDial;
dial->setMinimum(0);
dial->setMaximum(100);
QPushButton *pb_1 = new QPushButton();
pb_1->setText("Close");
QGridLayout *grid1 = new QGridLayout();
grid1->setContentsMargins(75, 45, 75, 25);
grid1->setHorizontalSpacing(20);
grid1->setVerticalSpacing(45);
grid1->addWidget(spinBox, 0, 0);
grid1->addWidget(progressBar, 0, 1);
grid1->addWidget(slider, 1, 0, Qt::AlignHCenter);
grid1->addWidget(dial, 1, 1, Qt::AlignHCenter);
QHBoxLayout *layout1 = new QHBoxLayout();
layout1->addStretch();
layout1->addWidget(pb_1);
layout1->addStretch();
QVBoxLayout *layoutMain = new QVBoxLayout(this);
layoutMain->addLayout(grid1);
layoutMain->addSpacing(75);
layoutMain->addLayout(layout1);
connect(spinBox,
cs_mp_cast<int>(&QSpinBox::valueChanged),
progressBar, &QProgressBar::setValue);
connect(progressBar,
cs_mp_cast<int>(&QProgressBar::valueChanged),
slider, &QSlider::setValue);
connect(slider,
cs_mp_cast<int>(&QSlider::valueChanged),
dial, &QSlider::setValue);
connect(dial,
cs_mp_cast<int>(&QDial::valueChanged),
spinBox, &QSpinBox::setValue);
connect(pb_1, &QPushButton::clicked,
this, &QWidget::close);
spinBox->setValue(42);
}
Line 5 creates a new QSpinBox object. The following two lines set the minimum and maximum range from 0 to 100. The defaults are 0 and 99 respectively. On lines 9 through 11 the font font size is read and then set to 10 points, which usually provides a better visual experience. Take a look at line 11, this is where the new font size is assigned back to the spinBox.
Lines 13 through 15 create a new QProgressBar and adjust the minimum and maximum values. The same happens for QSlider. A new QDial is created on line 21 and then the minimum and maximum values are assigned.
Line 28 introduces a class which can be used to layout widgets in a grid consisting or rows and columns. The next three lines of code adjust the margin and spacing of the grid and the distance between the elements which will be placed in the grid layout. If we look at the parameters on line 35, the slider object will be positioned in row 1 and column 0. This widget will also be horizontally aligned and centered within the column.
Lines 44 and 46 add the two layouts to layoutMain. It is important to remember that ownership of these five widgets have been transferred to the MainWindow. The passed value of “this” on line 43 is required so layoutMain will be attached to the current window.
Signal / Slot Connections
Now we want to set up four different connections for the GUI display widgets so all of them are updated whenever another one is changed. Since the progressBar is read only it will simply be updated as the other three are changed. The last call to connect() uses a slot to close the window when the push button is clicked.
Signal Overload
On line 49 the second parameter to connect() is a bit different from what we have seen in prior examples. The signal for QSpinBox has two overloads as shown below.
- valueChanged(const QString &text)
- valueChanged(int newValue)
We need a way to tell connect() which overload to use. This is the purpose of the cs_mp_cast<int> syntax. The connect() method will use the overload which accepts an int data type.
Initial Value
After everything is set up we initialize the value for spinBox on line 67. This line of code needs to go after the calls to connect(), otherwise the other three GUI display widgets would not be in sync until one of the other widgets was moved.
Main Function
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow *window = new MainWindow();
window->show();
return app.exec();
}
The source code for main() is the same as shown in example 3.
Running the Example
To build and run this example use the same CMake build file and commands as we showed for the first example. The only suggested modification is on line 2 of the CMakeLists.txt file, change “example_1” to “example_8”.