在这节中,我们要创建一个既小又简单的应用程序来演示如何使用布局管理一个窗口上的widget的形状以及如何使用信号和槽来同步两个widget。这个应用程序要求输入用户的年龄,用户可以操作一个spin box或者一个slider来输入年龄。
这个应用程序包含3个widget:一个QSpinBox,一个QSlider,和一个QWidget。QWidget是应用程序的主窗口。QSpinBox和QSlider在QWidget中渲染;它们是QWidget的children。换句话说,我们可以说QWidget是QSlider和QSlider的parent。QWidget本身没有parent因为它在窗口的顶层。QWidget和它所有的子类的构造函数都有一个QWidget指针形参用来表明parent的widget。
源代码如下:
- #include <QApplication>
- #include <QHBoxLayout>
- #include <QSlider>
- #include <QSpinBox>
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- QWidget *window = new QWidget;
- window->setWindowTitle("Enter Your Age");
- QSpinBox *spinBox = new QSpinBox;
- QSlider *slider = new QSlider(Qt::Horizontal);
- spinBox->setRange(0, 130);
- slider->setRange(0, 130);
- QObject::connect(spinBox, SIGNAL(valueChanged(int)),
- slider, SLOT(setValue(int)));
- QObject::connect(slider, SIGNAL(valueChanged(int)),
- spinBox, SLOT(setValue(int)));
- spinBox->setValue(35);
- QHBoxLayout *layout = new QHBoxLayout;
- layout->addWidget(spinBox);
- layout->addWidget(slider);
- window->setLayout(layout);
- window->show();
- return app.exec();
- }
第8,9行建立了用来作为应用程序主窗口的QWidget对象,我们调用setWindowTitle函数来设置显示在窗口标题栏的文字。
第10,11行创建了一个QSpinbox和一个QSlider对象,第12,13行设置了它们合理的范围。我们可以放心的假设用户最多130岁。我们本可以在QSpinBox和QSlider的构造函数中把window传进去,来指定构造出来的对象的parent是window,但是却没必要这样做,因为布局系统会解决这个问题并且自动的设置这些对象的parent,稍后我们会看到的。
第14到17行的这两个QObject::connect()调用确保spin box对象和slider对象同步,就是它们的值在任何一个对象的值改变时都保持一致。当一个对象的值改变时,它的valueChanged(int)信号就被发出了(emit),然后另一个对象setValue(int)槽将被调用来设置新的值。
第18行spin box对象的值被设为35。然后QSpinBox则发出valueChanged(int)信号并伴随着一个整型的参数35。这个参数被传送到QSlider的setValue(int)槽,可以把slider对象的值设为35。这个slider对象然后发出valueChanged(int)信号,因为它自己的值被改变了,就触发了spin box对象的setValue(int)槽。但是在这里setValue(int)槽不会发出任何信号,因为spin box的值已经是35了。这样可以组织无穷递归。下图则说明了这一情况。
第19行到第22行,我们使用layout manager(布局管理者)来为spin box对象和slider对象布局。一个布局管理者是一个负责设置它管理的widget的尺寸和位置的对象。Qt有3个布局管理者类:
QHBoxLayout水平的从左到右布局widgets(一些地方习俗是从右到左)。
QVBoxLayout垂直的从高到低布局widgets。
QGridLayout用网格来布局widgets。
第22行的QWidget::setLayout()调用把布局管理者安置到wndow对象上。在表面的背后,QSpinbox和QSlider被设为layout被安置的widget的children,处于这一点当我们构造一个将被放到一个layout的widget对象时我们没必要为它指明一个明确的parent。
虽然我们没有明确的设置任何一个widget的位置和尺寸,但QSpinbox和Qslider被非常好的挨个儿布局显示了出来。这时因为QHBboxLayout自动的为它负责的widgets指定了合理的位置和尺寸。这样布局管理者就把我们从枯燥无味的为我们的应用程序的widget硬编码的局面中解脱了出来,并且还确保窗口能平滑的调整大小。
Qt使得建立用户界面是一件容易理解且非常有弹性的事情,最常见的模式是它示例化Qt程序员所需的部件,然后根据需要设置它们的属性。程序员把各种widgets加到layouts中,layouts能自动完成调整尺寸和指定位置的工作。使用Qt的信号和槽机制能把widgets连接在一起,从而使用户界面的行为很好的管理起来。