该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
3、窗口布局
在本小节,我们将用一个样例来展现如何在窗口中规划各个部件的布局,并学习使用信
号和槽来使两个窗口部件同步。这个应用程序要求输入用户的年龄,使用者可以通过一个旋
转窗口或者一个滑块窗口来输入。
这个应用程序包括三个窗口部件:一个 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 (50);
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 行设置了 QWidget ,它将被作为程序的主窗口。我们调 用函数
setWindowTitle()来设置窗口的标题栏。
第 10 行和第 11 行创建了一个 QSpinBox 和一个 QSlider,第 12 行和第 13 行设置了它们
的取值范围(我们假设用户最大也只有 130 岁)。我们可以将之前创建的 QWidget 对象 window
传递给 QSpinBox 和 QSlider 的构造函数,用来说明这两个对象的父窗口,但是这么做并不
是必须的。原因是窗口布局系统将会自己指出这一点,自动将 window 设置为父窗口。我们
一会儿就可以看到这个特性。
在第 14 行和第 17 行,两个对于 QObject::connect()函数的调用确保了旋转窗口和滑块窗
口的同步,这样这两个窗口总是显示同样的数值。不管一个窗口对象的数值何时发生变化,
它的信号 valueChanged(int)就将被发射,而另一个窗口对象的槽 setValue(int)会接受到这个信
号,使得自身的数值与其相等。
第 18 行将旋转窗口的数值设置为 50。当这个事件发生的时候,QSpinBox 发射信号
valueChanged(int) ,这个信号包括一个值为 50 的整型参数。这个参数被 QSlider 的槽
setValue(int)接受,就会将滑块的值也设置为 50。由于 QSlider 的值被改变,所以 QSlider 也
会发出一个 valueChanged(int)信号并触发 QSpinBox 的 setValue(int)槽。但是在这个时候,
QSpinBox 不会再发出任何信号,因为旋转窗口的值已经被设置为 50 了。这将有效地防止信
号的无限循环。
从第 19 行到第 22 行,我们通过使用一个 layout 管理器对旋转窗口和滑块窗口进行了布
局设置。一个布局管理者就是一个根据窗口作用设置其大小和位置的对象。Qt 有三个主要
的布局管理类:
QHBoxLayout:将窗口部件水平自左至右设置(有些情况下是自右向左)。
QVBoxLayout:将窗口部件垂直自上向下设置。
QGridLayout: 以网格形式设置窗口部件。
第 22 行我们调用 QWidget::setLayout()函数在对象 window 上安装布局管理器。通过这
个调用,QSpinBox 和 QSlider 自动成为布局管理器所在窗口的子窗口。现在我们明白为什
么在设置子窗口时不用显式地说明父窗口了。
可以看到,虽然没有明显地给出任何窗口的大小和位置,但 QSpinBox 和 QSlider 是很
完美地被水平依次放置的。这是因为 QHBox-Layout 根据各个窗口的作用自动的为其设置了
合理的大小和位置。这个功能使我们从烦琐的界面调整中解放出来,更加专注于功能的实现。
Qt 构建用户界面的方法很容易理解,并且有很高的灵活性。Qt 程序员最常用的设计模
式是:说明所需要的窗口部件,然后设置这些部件必须的特性。程序员把窗口部件添加到布
局管理器中,布局管理器就将自动地设置这些部件的大小和位置。而用户界面的行为是通过
连接各个部件(运用信号/槽机制)来实现的。
4、派生 QDialog
我们现在开始尝试着在 Qt 里只用 C++语言而不是借助界面设计器来完成一个对话框:
FIND。我们将这个对话框作为一个类来完成,这么做的好处是我们使这个对话框成为了一
个独立的,拥有自己的信号和槽的,设备齐全的组件。
程序的源代码由两部分组成:finddialog.h 和 finddialog.cpp。我们从头文件开始。
1 #ifndef FINDDIALOG_H
2 #define FINDDIALOG_H
3 #include
4 class QCheckBox;
5 class QLabel;
6 class QLineEdit;
7 class QPushButton;
第 1 行,第 2 行(和第 27 行)的作用是防止头文件被重复包含。
第 3 行包含了 QDia