.ui 文件其实就一个标准 XML 格式的文本文件(感兴趣的读者可以用记事本打开看看),需要通过 uic 工具将其转换为项目里可用的 ui_*.h 头文件, 这个头文件里才是真正可用的 C++ 代码。
接下来我们以《Qt Designer的简单使用》中生成的 hello.ui 为例来讲解如何把 .ui 文件转换成 C++ 代码,以及如何使用 .ui 文件。
打开 Qt 命令行工具,进入 D:\QtDemo\ 文件夹:
cd /d D:\QtDemo\
执行 uic 命令:
uic hello.ui -o ui_hello.h
查看该头文件代码,内容如下:
/******************************************************************************** ** Form generated from reading UI file 'hello.ui' ** ** Created by: Qt User Interface Compiler version 5.9.0 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_HELLO_H #define UI_HELLO_H #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QHeaderView> #include <QtWidgets/QLabel> #include <QtWidgets/QWidget> QT_BEGIN_NAMESPACE class Ui_Form { public: QLabel *label; void setupUi(QWidget *Form) { if (Form->objectName().isEmpty()) Form->setObjectName(QStringLiteral("Form")); Form->resize(427, 244); label = new QLabel(Form); label->setObjectName(QStringLiteral("label")); label->setGeometry(QRect(10, 10, 200, 40)); retranslateUi(Form); QMetaObject::connectSlotsByName(Form); } // setupUi void retranslateUi(QWidget *Form) { Form->setWindowTitle(QApplication::translate("Form", "Form", Q_NULLPTR)); label->setText(QApplication::translate("Form", "C\350\257\255\350\250\200\344\270\255\346\226\207\347\275\221", Q_NULLPTR)); } // retranslateUi }; namespace Ui { class Form: public Ui_Form {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_HELLO_H
代码开头的注释提醒开发者不要手动修改该头文件,因为 uic 工具下次自动生成 .h 文件时,会把旧的代码全清掉,然后生成新的代码内容。
QT_BEGIN_NAMESPACE 和 QT_END_NAMESPACE 这两个宏标示中间的代码是包含在名字空间里的,就是一个提示作用,没有实际意义。
第一个类是全局范围定义的 Ui_Form 类,里面首先定义了一个 label 指针,注意这个指针名称就是之前设计师里显示的 objectName。
接着定义了一个 setupUi 函数,这个是最关键的生成图形界面的函数,它接收一个 QWidget 对象的指针,然后为这个 QWidget 对象设置窗口界面和控件。
还有一个 retranslateUi 函数,是专门用于支持多国语言翻译的,主窗口和标签控件的字符串都在这重新翻译一下,如果有多国语言支持的翻译文件,界面的多国语言显示就通过该函数实现。
这两个函数细节就不讲解了,以后还会遇到,而且它们都是 uic 自动生成的,不需要我们手动编写或修改,不用太担心细节,学会用这个头文件就可以了。
接下来定义了一个叫 Ui 的名字空间,空间里定义了一个类 Form ,简单地从 Ui_Form 类继承一下,并没有添加额外的代码。使用 Ui 名字空间的好处就是避免名称冲突,所以正常都不会直接使用 Ui_Form 类,而是用名字空间里的 Ui::Form 类。
需要注意的是 ui_hello.h 头文件里没有 Q_OBJECT 宏,它里面定义的类也没有从任何窗口或控件类继承。无论是 Ui_Form 类还是 Ui::Form 类,它们都不是窗口类!
准确地说,它们通过 setupUi 函数,辅助该函数参数里的窗口对象(QWidget *Form)构建图形界面,它们帮助别的窗口类对象构建图形界面,仅此而已。当然,在 setupUi 函数里新建的控件指针,如 label,是 Ui_Form 或Ui::Form 类里的成员变量,代码里需要通过这个类的成员变量来操控相应的控件。
如果要在项目里面使用 ui 文件(其实是 ui_*.h),通常有三种方式:直接使用方式、多重继承使用方式和成员变量使用方式。本节讲述前两种使用方式,而以后 Qt Creator 自动生成的代码就是成员变量使用方式,本节就不重复了。
直接使用 .ui 文件的原理非常简单,创建一个 QWidget 类对象和 Ui::Form 类对象,调用 Ui::Form 对象的 setupUi 函数设置一下主窗体,然后显示就行了。我们在 D:\QtDemo\ 文件夹里新建一个 main.cpp,然后编辑代码如下:
#include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include "ui_hello.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget *w = new QWidget(); //主窗口 Ui::Form createUi; //createUi并不是一个真正的窗口 createUi.setupUi(w); //createUi是创建GUI的工具 w->show(); //w是真正的窗口 return a.exec(); }
main.cpp 包含了三个头文件 QApplication、QWidget 和 前面用 uic 生成的 ui_hello.h,由于 ui_hello.h 不包含 Q_OBJECT 宏,是不需要用元对象编译器 moc 处理的。
main 函数里第一行是图形界面程序入口对象,第二行创建了一个 QWidget 类对象 w(w 其实是一个指向对象的指针)作为程序的主窗口,w 自己并没有创建控件或设置窗口属性。
第三行语句:
Ui::Form createUi;
创建了 Ui::Form 类的对象 createUi ,这个对象自己不是一个窗口,它可以为别的窗口对象设置图形界面。
第四行语句:
createUi.setupUi(w);
调用了 createUi 对象的 setupUi 函数,该函数接收一个窗体对象指针,这里是 w。setupUi 函数里面的代码会为 w 创建内部的控件,设置窗体大小等等。
剩下的两行代码是显示主界面,并进入事件处理循环,直到退出。
代码解释完了,接下来我们就开始编译把。
打开 Qt 命令行工具,进入 D:\QtDemo 文件夹:
cd /d D:\QtDemo
执行 g++ 命令:
g++ main.cpp -std=c++0x -I"D:\Qt\5.9\mingw53_32\include" -L"D:\Qt\5.9\mingw53_32\lib" -lQt5Core -lQt5Gui -lQt5Widgets -o main
编译链接成功后,在输入main.exe
命令就可以看到运行效果。以下是完整流程的截图: