本节主要是把基本的C++知识与QT所提供的功能组合起来创建一些简单的图形用户界面应用程序。
Hello QT
首先创建一个简单的QT程序
#include <QApplication>
#include <QLabel>
int main(int argc,char *argv[]){
QApplication app(argc,argv);
QLabel *label=new QLabel("Hello QT!");
label->show();
return app.exec();
}
程序运行结果:
程序分析:
第1行和第2行包含了类QApplication和QLabel的定义。对于每个QT类,都有一个与该类同名的头文件,在这个头文件中包含了对该类的定义。
第5行创建了一个QApplication对象,用来管理整个应用程序所用到的资源。
第6行创建了一个显示“Hello QT”的QLabel窗口部件(widget)。在QT的术语中,窗口部件就是用户界面中的一个可视化元素。该此起源于“window gadget”(窗口配件)这两个词,相当于Window系统术语中的“控件”(control)和“容器”(container)。按钮、菜单、滚动条和框架都是窗口部件。窗口部件可以包含其他窗口部件,例如,应用程序的窗口通常就是一个包含了QMenuBar、QToolBar、QStatusBar以及一些其他窗口部件的窗口部件。绝大多数应用程序都会使用一个QMainWindow或者一个QDialog来作为它的窗口。但QT是如此灵活,以至于任意窗口部件都可以作为窗口。在本例中,就是用窗口部件QLabel作为应用程序的窗口。
第7行使QLabel标签label可见。在创建窗口部件的时候,标签通常都是隐藏的,这就允许我们可以先对其进行设置,然后再显示它们,从而避免了窗口部件闪烁的现象。
第8行将应用程序控制权传递给QT。此时,程序就会进入事件循环状态,这是一种等待模式,程序会等候用户的动作,例如鼠标单击和按键操作。用户的动作会让可以产生响应的程序生成一些事件(event,也称为消息),这里的响应通常就是执行一个或多个函数。例如,当用户单击窗口部件时,就会产生一个“鼠标按下”事件和一个“鼠标松开”事件。
建立连接
编写一个应用程序,这个应用程序由一个按钮构成,用户可以单击这个按钮退出程序。
#include <QApplication>
#include <QPushButton>
int main(int argc,char *argv[]){
QApplication app(argc,argv);
QPushButton *button=new QPushButton("Quit");
QObject::connect(button,SIGNAL(clicked()),&app,SLOT(qutit()));
button->show();
return app.exec();
}
程序运行效果:
QT的窗口部件通过发射信号(signal)来表明一个用户动作已经发生了或者一个状态已经改变了。例如,当用户单击QPushButton时,该按钮就会发射一个clicked()信号。信号可以与函数(在这里称为槽,slot)相连接,以便在发射信号时,槽可以得到自动执行。在本例中,我们把这个按钮的clicked信号与QApplication对象的quit()槽连接起来。宏SIGNAL()和SLOT()是QT语法中的一部分。
窗口部件的布局
编写应用程序,可以用来询问用户的年龄,而用户可以通过操作微调框(spin box)或者滑块(slider)来完成年龄的输入。
应用程序由三个窗口部件组成:一个QSpinBox,一个QSlider和一个QWidget。QWidget是在这个应用程序的主窗口。QSpinBox和QSlider会显示在QWidget中,它们都是QWidget窗口部件的子对象,换而言之,QWidget窗口部件是QSpinBox和QSlider的父对象。QWidget窗口部件自己则没有父对象,因为程序是把它当作顶层窗口。QWidget的构造函数以及它的所有子类都会带有一个参数QWidget*,用来说明谁是它们的父窗口部件。
以下是QT类的继承树(只是一部分):
#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行设置它们的有效范围。本应该把QWidget窗口传递给QSpinBox和QSlider的构造函数,以说明这两个窗口部件的父对象都是这个窗口,但是没有这个必要,因为布局系统将会自行得出这一结果并自动把该窗口设置为微调框和滑块的父对象。
在程序的第19行到第22行,使用一个布局管理器对微调框和滑块进行布局处理。布局处理器(layout manager)就是一个能够对其所负责窗口部件的尺寸大小和位置进行设置的对象。
QT有三个主要的布局管理器类:
1.QHBoxLayout:在水平方向上排列窗口部件,从左到右。
2.QVBoxLayout:在竖直方向上排列窗口部件,从上到下。
3.QGridLayout:把各个窗口部件排列在一个网格中。
第22行中的setLayout()函数调用会在窗口上安装该布局管理器。从软件的底层实现上来说,QSpinBox和QSlider会自动重定义父对象,它们会成为这个安装了布局的窗口部件的子对象,也正是基于这种原因,当创建一个需要放进某个布局中的窗口部件时,就没有为其显式地指定父对象了。
总结
编写QT程序,最常使用的方式是先声明所需要的窗口部件,然后再设置它们所应具备的属性。程序员把这些窗口部件添加到布局中,布局会自动设置它们的位置和大小。利用QT的信号和槽机制,并通过窗口部件之间的连接就可以管理用户的交互行为。