13.6 构建 Qt 应用程序

利用一套工具,Qt 开发人员可以简化在所有支持平台中构建应用程序的流程。描述应 用程序、库和插件的项目文件被用来为每个平台生成适当的 makefile。

.pro 文件描述了各个项目,该文件以文本方式概述了源文件、头文件、 Qt Designer 窗体以及其他资源。这些资源都是由 qmake 工具来处理的,以便为每个平台中的项目生成 适当的 Makefile。

项目文件可描述 Qt 的所有库、工具以及示例。例如,只需以下三行即可描述 Qt 4 的 HTTP 示例:

HEADERS += httpwindow.h
SOURCES += httpwindow.cpp main.cpp
QT += network

前两个定义将构建此示例所需的头文件和源文件告知 qmake; 而最后一个定义则确保 使用 Qt 的网络连接库。使用项目文件语法,开发人员可以使用配置选项对编译流程进行精 细调节,并可为不同的部署环境编写各种有条件的编译规则。

此外,使用项目文件可以描述处于目录树层次较深位置的项目。 例如,Qt 示例位于顶 级 examples 目录内的目录树中。examples.pro 文件要求 qmake 深入到含有下列行的各类 示例的目录中:

TEMPLATE = subdirs
SUBDIRS = dialogs draganddrop itemviews layouts linguist \
mainwindows network painting richtext sql \
threads tools tutorial widgets xml

支持条件编译意味着 Windows 示例程序只有在 windows 操作系统下的 Qt windows 版 本时才会被编译。

win32:!contains(QT_EDITION, OpenSource|Console):SUBDIRS += activeqt

使用 qmake 编译项目时,编译套件中的其他工具自动会提供 Qt 的所有增强功能:moc将处理头文件以启用信号和槽;rcc 将编译指定的资源; 而 uic 则可用来根据用户界面创建代码。

pkg-config 集成支持预编译头文件,可以生成 Visual Studio 项目文件;以及其他高 级功能,可以支持开发人员在针对常见项目组件使用跨平台构建系统的同时,还支持其利用 与平台特定相关的工具。

更为深入的信息,请参考本书的附录,那里有 qmake 以及 make 命令的详细介绍。 13.7 问题与解答

问:什么情况下可以断开信号与槽的关联? 答:有 3 种情况需要断开信号与槽的关联: 1.断开与某个对象相关联的任何对象

这似乎有点不可理解,事实上,当我们在某个对象中定义了一个或者多个信号,这些 信号与另外若干个对象中的槽相关联,如果我们要切断这些关联的话,就可以利用这个方 法,非常之简洁。

disconnect( myObject, 0, 0, 0 );

或者

myObject->disconnect();

2.断开与某个特定信号的任何关联

disconnect( myObject, SIGNAL(mySignal()), 0, 0 )

或者

myObject->disconnect( SIGNAL(mySignal()) )

3.断开两个对象之间的关联。

disconnect( myObject, 0, myReceiver, 0 )

或者

myObject->disconnect( myReceiver )

在 disconnect 函数中 0 可以用作一个通配符,分别表示任何信号、任何接收对象、接 收对象中的任何槽函数。但是发射者 sender 不能为 0,其它三个参数的值可以等于 0。

问:Qt 的元对象系统还有哪些功能?

答: 除了提供在对象间进行通讯的机制外,元对象系统还包含以下几种功能:

1.QObject::metaObject() 方法

它获得与一个类相关联的 meta-object。

2.QMetaObject::className() 方法

在运行期间返回一个对象的类名,它不需要本地 C++编译器的 RTTI(run-time type information)支持。

3.QObject::inherits() 方法

它用来判断生成一个对象类是不是从一个特定的类继承出来,当然,这必须是在 QObject 类的直接或者间接派生类当中。

4.QObject::tr() and QObject::trUtf8()

这两个方法为软件的国际化翻译字符串 。

5.QObject::setProperty() and QObject::property()

这两个方法根据属性名动态的设置和获取属性值 。

除了以上这些功能外,它还使用 qobject_cast()方法在 QObject 类之间提供动态转 换,qobject_cast()方法的功能类似于标准 C++的 dynamic_cast(),但是 qobject_cast() 不需要 RTTI 的支持,在一个 QObject 类或者它的派生类中,我们可以不定义 Q_OBJECT 宏。如果我们在一个类中没有定义 Q_OBJECT 宏,那么在这里所提到的相应的功能在这个类 中也不能使用,从 meta-object 的观点来说,一个没有定义 Q_OBJECT 宏的类与它最接近的 那个祖先类是相同的,那就是说, QMetaObject::className() 方法所返回的名字并不是这 个类的名字,而是与它最接近的那个祖先类的名字。 所以,我们强烈建议,任何从 QObject 继承出来的类都定义 Q_OBJECT 宏。

问:在 Qt 中怎么响应事件,比如鼠标点击事件,键盘敲击事件等。

答:你需要在程序中重载下列函数,具体可以查阅 Qt Assistant。

mousePressEvent(QMouseEvent *event)
{
    //要做的事
}
keyPressEvent(QkeyEvent *event)
{
    //要做的事(键盘)
}