前面几节做了很多铺垫,终于啰嗦完了,从本节开始,我们就要接触真正的 Qt 代码了。
Qt 本身就是用 C++ 语言编写的,所以 Qt 程序的代码看起来和普通的 C++ 代码差不了多少, 这样就很容易上手,也适合自学。
C++ 的套路就编写一个类,使用的时候就定义该类的对象, 然后调用对象的函数来完成任务。最简化的 Qt 程序如下所示:
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow w;
w.setWindowTitle("Widgets演示"); //设置标题
w.resize(300, 140); //设置客户区大小
QLabel label("城东书院", &w);
label.setGeometry(100, 50, 160, 30);
w.show();
return app.exec();
}
接着我们对代码进行剖析。
第 1~3 行代码引入对应的头文件。在 Qt 中,头文件设计的非常规范,大部分情况下一个类对应一个头文件,类名和头文件名相同,以字母Q开头。一个控件对应一个类,要想使用控件,必须包含对应的头文件。
Qt 中的头文件被分门别类地放到了不同的文件夹。对于 Qt 5.9.0 MinGW 版本,头文件位于安装目录下的 \5.9\mingw53_32\include\ 文件夹中,使用 g++ 编译器时,通过-I选项可以指定头文件的路径。
与界面相关的 Qt 控件一般都位于安装目录下的 \5.9\mingw53_32\include\QtWidgets\ 文件夹,当使用-I选项指定头文件检索路径后,通过#include <QtWidgets/QLabel>这样的语句就可以成功引入头文件。
Qt 程序的入口函数和 C++ Console 程序一样,都是 main() 函数;参数也是一样的。不了解的读者请猛击:main()函数的高级用法:接收用户输入的数据
第 7 行创建了一个 QApplication 对象。QApplication 类主要用来管理程序的生命周期(包括初始化设置和销毁工作),开启事件循环。对于任何一个 Qt GUI 程序,必须有且仅有一个 QApplication 对象,但可以存在零个或多个窗口。
main() 函数一般以创建 QApplication 对象开始,后面才是实际业务的代码。
第 9 行代码中,QMainWindow 表示主窗口,它是一个顶级窗口。QMainWindow 可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,可以作为 GUI 程序的主窗口。
第 13 行通过 QLabel 创建了一个标签控件;标签控件的作用很简单,就是用来显示一段文本。构造函数的第一个参数指定了要显示的文本,第二个参数指定了父窗口。
在 Qt 中,一个控件可以有父辈,这个父辈可以是一个窗口,也可以是一个容器。父辈有管理控件的作用,当父辈被销毁时,子控件也都被销毁并释放内存。
第 14 行设置 Label 控件的几何尺寸,100 为左边距,50 为上边距,160 为控件宽度,30 为控件高度,单位都是像素(px)。边距是相对父辈 w 来说的。
第 15 行用来显示控件。控件被创建后只是分配了内存,并不可见,还需要调用 show() 函数显示出来。w 是 label 的父辈,父辈调用 show() 函数也会显示所有子控件,所以 label 就不需要再调用 show() 了。
exec() 使程序进入消息循环,等待可能发生的事件,例如鼠标点击、键盘输入等。这里 main() 把控制权转交给 Qt,由 Qt 完成事件处理工作,程序退出时 exec() 的值就会返回。在 exec() 中,Qt 接受并处理用户和系统的事件,把它们传递给适当的窗口控件。
关于消息循环,在《Windows编程》中已经进行了详细介绍,不了解的读者请自行脑补。
如果用户点击窗口的关闭按钮, 程序就会自动结束并返回一个值,默认是 0 。
图形程序与命令行程序一个最大的不同就是图形程序通常不会自动关闭,而是一直等待用户操作,所以图形程序与用户的交互性都很强。一般的命令行程序跑完自己就结束了,而图形程序会等待用户点击关闭按钮(或退出菜单项)才会结束。