本系列文章所用的平台:

  • Qt:4.8 和 5.1.1
  • Qt Creator:3.0

Qt 简介

Qt是一个跨平台应用程序和 UI 开发框架。使用 Qt 您只需一次性开发应用程序,无须重新编写源代码,便可跨不同桌面和嵌入式操作系统部署这些应用程序。Qt 提供了几个工具软件:

  • Qt Creator - 一个跨平台的Qt IDE,可单独使用,也可与 Qt 库和开发工具组成一套完整的SDK。
  • Qt Assistant - 快速地发现你所需要的帮助
  • Qt Designer - 可视化地设计视窗
  • Qt Linguist - 翻译应用程序使之能够进入国际市场
  • Qt QDbusViewer - 调试 D-Bus 程序

安装

  1. 官方下载地址:http://download.qt-project.org/

其中 snapshots 里面包含了最新测试版本; official releases 里面包含了官方发布版,即最终发布版; archive 里面是 Qt 4.7 及以前版本,Qt Creator 2.5 及以前版本。

  1. ArchLinux 安装预编译的版本:
  • Qt 4:

1
$ pacman -S qt4

  • Qt 5:

1
$ pacman -S qt5-tools

Hello World

Qt 4

  1. 创建工程目录 HelloWorld

1
$ mkdir HelloWorld

  1. 进入该目录

1
$ cd HelloWorld

  1. 新建一个文件 main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <QApplication>
#include <QLabel>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel hello("<center>Hello World!</center>");
hello.setWindowTitle("First Application");
hello.resize(400, 400);
hello.show();
return app.exec();
}

  1. 创建 Qt 工程文件

1
$ qmake -project

  1. 生成 Makefile

1
$ qmake

  1. 编译生成最终的可执行程序

1
$ make

Qt 5

与上面的步骤基本相同。但要在第4步生成 HelloWorld.pro 工程文件后往里添加一句话。

第4步调用 qmake -project 命令后生成的 HelloWorld.pro 内容如下:

1
2
3
4
5
6
TEMPLATE = app
TARGET = QtHelloWorld
INCLUDEPATH += .
# Input
SOURCES += main.cpp

将内容修改为:

1
2
3
4
5
6
7
8
TEMPLATE = app
TARGET = QtHelloWorld
QT += core gui
QT += widgets
INCLUDEPATH += .
# Input
SOURCES += main.cpp

其余步骤完全相同。

Qt 的编译流程

The Qt build system

moc

标准 C++ 对象模型在运行时效率方面卓有成效,但是在某些特定问题域下的静态特性就显得捉襟见肘。GUI 界面需要同时具有运行时的效率以及更高级别的灵活性。为了解决这一问题,Qt “扩展”了标准 C++。所谓“扩展”,实际是在使用标准 C++ 编译器编译 Qt 源程序之前,Qt 先使用一个叫做 moc(Meta Object Compiler,元对象编译器)的工具,先对 Qt 源代码进行一次预处理(注意,这个预处理与标准 C++ 的预处理有所不同。Qt 的 moc 预处理发生在标准 C++ 预处理器工作之前,并且 Qt 的 moc 预处理不是递归的。),生成标准 C++ 源代码,然后再使用标准 C++ 编译器进行编译。

Qt 使用 moc,为标准 C++ 增加了一些特性:

  • 信号槽机制,用于解决对象之间的通讯,这个我们已经了解过了,可以认为是 Qt 最明显的特性之一;
  • 可查询,并且可设计的对象属性;
  • 强大的事件机制以及事件过滤器;
  • 基于上下文的字符串翻译机制(国际化),也就是 tr() 函数;
  • 复杂的定时器实现,用于在事件驱动的 GUI 中嵌入能够精确控制的任务集成;
  • 层次化的可查询的对象树,提供一种自然的方式管理对象关系。
  • 智能指针(QPointer),在对象析构之后自动设为 0,防止野指针;
  • 能够跨越库边界的动态转换机制。

通过继承 QObject 类,我们可以很方便地获得这些特性。当然,这些特性都是由 moc 帮助我们实现的。moc 其实实现的是一个叫做元对象系统(meta-object system)的机制。正如上面所说,这是一个标准 C++ 的扩展,使得标准 C++ 更适合于进行 GUI 编程。虽然利用模板可以达到类似的效果,但是 Qt 没有选择使用模板。按照 Qt 官方的说法,模板虽然是内置语言特性,但是其语法实在是复杂,并且由于 GUI 是动态的,利用静态的模板机制有时候很难处理。而自己使用 moc 生成代码更为灵活,虽然效率有些降低(一个信号槽的调用大约相当于四个模板函数调用),不过在现代计算机上,这点性能损耗实在是可以忽略。

深入阅读

  1. QtDoc 5.0: CMake Manual
  2. Using CMake to Build Qt Projects
  3. The Transition from Qt 4.x to Qt 5