在这个小节中,我们说明在一个窗口中如何对多个控件进行布局排列,以及学习利用信号和槽使控件同步。程序要求用户通过spin box或者slider输入年龄。
程序中使用了三个控件:QSpinBox,QSlider和QWidget。QWidget是这个程序的主窗口。QSpinBox和QSlider被放在QWidget中;他们是QWidget的孩子。反过来,我们也可以称QWidget是QSpinBox和QSlider的父亲。QWidget自身没有父亲,因为它是程序的顶层窗口。在QWidget及其子类的构造函数中,都有一个QWidget*参数,用来指定它们的父控件。
源代码如下:- 1 #include
- 2 #include
- 3 #include
- 4 #include
- 5 int main(int argc, char *argv[])
- 6 {
- 7 QApplication app(argc, argv);
- 8 QWidget *window = new QWidget;
- 9 window->setWindowTitle("Enter Your Age");
- 10 QSpinBox *spinBox = new QSpinBox;
- 11 QSlider *slider = new QSlider(Qt::Horizontal);
- 12 spinBox->setRange(0, 130);
- 13 slider->setRange(0, 130);
- 14 QObject::connect(spinBox, SIGNAL(valueChanged(int)),
- 15 slider, SLOT(setValue(int)));
- 16 QObject::connect(slider, SIGNAL(valueChanged(int)),
- 17 spinBox, SLOT(setValue(int)));
- 18 spinBox->setValue(35);
- 19 QHBoxLayout *layout = new QHBoxLayout;
- 20 layout->addWidget(spinBox);
- 21 layout->addWidget(slider);
- 22 window->setLayout(layout);
- 23 window->show();
- 24 return app.exec();
- 25 }
复制代码 第8,9行建立程序的主窗口控件,设置标题。
第10到13行创建主窗口的children,并设置允许值的范围。我们可以把window 传递给QSpinBox 及 QSlider 的构造函数以指明window 是这些控件的父控件,但此处没必要,因为布局系统会自动判别设置。
第14到第17行是spinBox和slider的连接,以使之同步显示同一个年龄值。不管哪个控件的值发生变化,都会发出valueChanged(int)信号,另一个控件的setValue(int)槽函数就会为这个控件设置一个新值。
第18行将spinBox的值设置为35,这时spinBox发出valueChanged(int)信号,int的参数值为35,这个参数传递给slider的setValue(int)槽,将slider的值也设置为35。同理,slider也会发出valueChanged(int)信号,触发spinBox的setValue(int)槽。这个时候,因为spinBox的当前值就是35,所以spinBox不会发送任何信号,不会引起死循环。
第19至22行,我们使用了一个布局管理器排列spinBox和slider控件。布局管理器能够根据需要确定控件的大小和位置。Qt有三个主要的布局管理器类:
QHBoxLayout:水平排列控件。
QVBoxLayout:垂直排列控件。
QGridLayout:网格排列控件。
第22行,QWidget::setLayout()把这个布局管理器放在window上。这个语句将spinBox和slider的“父”设为window,即布局管理器所在的控件。如果一个控件由布局管理器确定它的大小和位置,创建它的时候就不必指定一个明确的“父”控件。
现在,虽然我们还没有看见spinBox和slider控件的大小和位置,它们已经水平排列好了。QHBoxLayout能合理安排它们。我们不用在程序中考虑控件在屏幕上的大小和位置这些头疼的事情了,交给布局管理器就ok了。
在Qt中建立用户界面就是这样简单灵活。程序员的任务就是实例化所需要的控件,按照需要设置它们的属性,把它们放到布局管理器中。界面中要完成任务由Qt的信号和槽完成。
|