.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);} // setupUivoid 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 文件

直接使用 .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命令就可以看到运行效果。以下是完整流程的截图:

在本例中,图形界面的构建和设置代码全部交给 createUi 对象了。这就是可视化编程的典型示范,创建和设置图形界面的代码就用 Qt Designer 和 uic 来完成,其他的后台代码自己编写。将开发者从凭空想象图形界面变成直接拖动控件,这样不仅直观,而且开发者需要动手编的代码也变少了。

将图形界面设计和后台功能代码相分离,是现代 GUI 程序设计的通用思路。

多重继承法使用 .ui 文件

上面的代码非常简单,除了 uic 生成的 ui_hello.h 和手动编写的 main.cpp,就没其他的代码文件了。主界面是 QWidget 类的对象,然后该对象比较简单,没有自己的代码。

如果要丰富一下主界面的窗口类,那就需要使用从 QWidget 类继承的方式并加上 Ui::Form 类的代码。C++ 如果要同时使用两个类的代码,有两种方式:

  • 一种是多重继承的方式,同时用 QWidget 和 Ui::Form 类作为基类;
  • 还有一种是使用成员变量,将 Ui::Form 类的对象作为 QWidget 派生类的成员变量,这种也叫单一继承方式,它的基类只有 QWidget。

本小节介绍多重继承方式,而以后的代码都用 QtCreator 自动生成的单一继承方式(Ui::Form 的对象作为成员变量)。

将前面做好的 hello.ui 和 ui_hello.h 复制到 D:\QtDemo 文件夹,然后再新建三个代码文件,分别是 hellouiwidget.h、hellouiwidget.cpp 和 main.cpp ,每个文件的内容如下。

  1. hellouiwidget.h 代码内容
#include <QtWidgets/QWidget>
#include <QtWidgets/QLabel>
#include "ui_hello.h"
class HelloUIWidget : public QWidget, public Ui::Form
{Q_OBJECT
public:explicit HelloUIWidget(QWidget *parent = 0);~HelloUIWidget();
protected:void AdjustLabel();
};

hellouiwidget.h 包含了三个头文件 QWidget、QLabel 和 使用 uic 生成的 ui_hello.h ,里面定义了一个类 HelloUIWidget 。HelloUIWidget 从 QWidget、Ui::Form 两个基类继承而来,都是 public 继承方式。由于基类有一个是 Qt 窗口类 QWidget,所以在类定义开始处必须加入 Q_OBJECT 宏,用于声明元对象系统。

该类定义了两个公开类型(public)的函数,即构造函数和析构函数。

最后一个是我们自己编写的保护类型(protected)的函数 AdjustLabel,用于调整 label 标签对象的显示效果。使用多重继承或成员变量的方式就容易丰富窗口类的功能,我们在 HelloUIWidget 里添加了 AdjustLabel 函数,当然还可以添加更多的函数。

  1. hellouiwidget.cpp 文件内容:
#include "hellouiwidget.h"
HelloUIWidget::HelloUIWidget(QWidget *parent) : QWidget(parent)
{setupUi(this);  //必须先调用setupUi 函数//TODO:AdjustLabel();
}
HelloUIWidget::~HelloUIWidget()
{//无需手动删除 Label 组件和 widget 组件,它们会被 Qt 自动删除
}
void HelloUIWidget::AdjustLabel()
{label->setText("C语言中文网");
}

在 HelloUIWidget 构造函数定义处,它使用输入参数 parent 初始化了基类 QWidget,另一个基类 Ui::Form 因为它构造函数不需要参数,就没必要手动编写初始化代码,C++ 编译器自己会先构造好基类。

HelloUIWidget 从基类 Ui::Form 继承了 setupUi 函数,所以可直接调用该函数为自己窗口(this)构建图形界面。在构建好图形界面的控件之后,我们再调用自己编写的 AdjustLabel 函数修改标签控件显示效果。

第二个函数是 HelloUIWidget 类的析构函数,里面没有实际代码。仔细观察 ui_hello.h 代码可以发现 label 指针保存的对象是用 new 创建的,而这里我们没有手动 delete 它,因为在 Qt 主窗口关闭时,这些控件会随着主窗口全会被自动销毁,对于控件对象可以不用手动编写 delete 代码。

第三个函数是 AdjustLabel ,这个函数里对 label 指针保存的对象进行处理,label 指针成员变量也是从基类 Ui::Form 继承而来的。AdjustLabel 里面第一句代码:

label->setText(“C语言中文网”);

是设置标签控件显示的文本。

  1. main.cpp 文件内容:
#include <QtWidgets/QApplication>
#include "hellouiwidget.h"
int main(int argc, char *argv[])
{QApplication a(argc, argv);HelloUIWidget *w = new HelloUIWidget();w->show();return a.exec();
}

代码内容比较简单,main 函数里第一句创建图形程序的入口对象,第二句创建主界面窗口对象,第三句显示主界面窗口,最后一句进入事件循环直到退出为止。窗口对象会在主窗口关闭时自动销毁,所以没有 手动加 delete 代码。

代码分析完了,接下来就是编译生成目标程序了。

  1. 打开 Qt 命令行工具,进入 D:\QtDemo 文件夹:

cd /d D:\QtDemo

  1. 用 uic 生成 ui_hello.h:

uic hello.ui -o ui_hello.h

  1. 用 moc 生成元对象系统代码:

moc hellouiwidget.h -o moc_hellouiwidget.cpp

因为 ui_hello.h 头文件里面没有 Q_OBJECT 宏,所以不需要处理,只给 hellouiwidget.h 生成元对象系统代码就够了。

  1. 生成可执行程序:

g++ moc_hellouiwidget.cpp hellouiwidget.cpp 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

  1. 输入main.exe命令就可以运行生成的程序了。

用 qmake 生成程序

上面通过自己用 uic、moc、g++ 命令生成目标程序,需要执行的命令是比较多的。之所以费力气讲解编译链接过程的步骤,就是希望读者多了解些知识,如果将来遇上编译或链接时的错误,就可以对号入座,看看大概是哪里出的问题。如果不了解这些过程,可能在编译时少个 ui_.h 或 moc_.cpp 就会傻眼了。

接着我们介绍傻瓜式的生成方法,就是用 qmake 工具。在开始之前,把 D:\QtDemo 文件夹里面生成的中间文件 ui_hello.h、moc_hellouiwidget.cpp、.o 、.exe 全删了,保留我们手动编辑的 hello.ui、hellouiwidget.h、hellouiwidget.cpp、main.cpp 四个文件就够了。

  1. 打开 Qt 命令行工具,进入 D:\QtDemo 文件夹:

cd /d D:\QtDemo

  1. 使用 qmake 生成 .pro 项目文件:

qmake -project “QT+=widgets”

-project选项就是为当前文件夹里的代码创建项目文件,本例子默认得到的是 QtDemo.pro ,就是文件夹名字加上 .pro

QT+=widgets是我们手动给 pro 文件加了一行,添加了 QtWidgets 模块(widgets),pro 文件默认就带有 QtCore(core)和 QtGui(gui)两个模块,不需要手动添加 core 和 gui 。

  1. 使用 qmake 生成 Makefile:

qmake

不带选项和参数的 qmake 默认就是为项目生成 Makefile,运行之后会在项目文件夹里生成 debug 和 release 两个文件夹,以及 Makefile、Makefile.Debug、Makefile.Release 三个生成脚本文件。

  1. 使用 make 工具生成目标程序:

mingw32-make all

这条命令会把调试版和发行版的目标程序全都生成。

  1. 运行生成好的目标程序:
    Debug 调试版本程序:

debug\QtDemo.exe

Release 发行版本程序:

release\QtDemo.exe

运行效果就不重复展示了,和前面的是一样的。

可见用 qmake 生成目标程序就是傻瓜式的三板斧:

  • 先用 qmake -project 生成项目 pro 文件;
  • 再直接用 qmake 生成 Makefile;
  • 最后 make all 。

qmake 把许多 uic、moc、g++ 编译链接过程的命令都自动生成了,全放在 Makefile 脚本里,用起来就特别省事。qmake 创建的各种自动生成命令要比我们自己之前编的命令更为科学合理,感兴趣的读者可以记录一下 mingw32-make 命令执行时命令行里出现的各种生成命令,这些命令都类似于以后的 QtCreator 集成开发环境里面生成程序用的命令。

因为本节引入了 ui 文件,我们来看看本节 pro 文件与《使用qmake工具提升效率》中的有哪些变化:

######################################################################
# Automatically generated by qmake (3.1) Wed Jun 5 13:55:11 2019
######################################################################

QT+=widgets
TEMPLATE = app
TARGET = QtDemo
INCLUDEPATH += .

# The following define makes your compiler warn you if you use any
# feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

# Input
HEADERS += hellouiwidget.h
FORMS += hello.ui
SOURCES += hellouiwidget.cpp main.cpp

《使用qmake工具提升效率》中例子没有 hello.ui 文件,本节多的 hello.ui 在 pro 文件里就是对应倒数第二行:

FORMS += hello.ui

这句意思就是添加一个构建窗体的 hello.ui 文件,qmake 生成的 Makefile 脚本会自动将 hello.ui 转换成 ui_hello.h,也会自动为 hellouiwidget.h 生成 moc_hellouiwidget.cpp ,为开发人员省了很多事。

最后用一张图展示本节例子的整个生成过程,不论是自己一句句敲命令还是用 qmake 生成,大致的过程都是如下图所示:

Qt .ui文件的使用相关推荐

  1. 【Qt】Visual Studio中无法打开Qt中UI文件

    00. 目录 文章目录 00. 目录 01. 问题描述 02. 开发环境 03. 问题分析 04. 问题解决 05. 预留 01. 问题描述 使用Visual Studio打开纯Qt项目之后, 点击Q ...

  2. Python Qt GUI设计:将UI文件转换为Python文件的三种妙招(基础篇—2)

    目录 1.创建项目 2.将.ui文件生成.py文件 2.1.Eric 6编译 2.2.Python命令行编译 2.3.脚本编译 3.界面.逻辑分离思想 在开始本文之前提醒各位朋友,Python记得安装 ...

  3. Qt探秘——谈ui文件的用法

    相信用过Qt Designer的朋友,对Qt Project中的.ui文件并不陌生.这个文件在Qt Designer中并不能直接修改其源代码,而只能通过Qt Designer的图形工具对其进行操作.对 ...

  4. 关于Qt Designer程序/UI文件打开未响应的解决方法

    关于Qt Designer程序/UI文件打开未响应的解决方法 参考文章: (1)关于Qt Designer程序/UI文件打开未响应的解决方法 (2)https://www.cnblogs.com/ys ...

  5. 在Qt中如何使用QtDesigner创建的UI文件(一) (转)

    使用Qt有一些时间了,一直在IDE环境(qtcreator和VS2003+集成器)中使用,自然少了很多麻烦的步骤.但是在享受这种便利的同时,我们也失去了理解更多知识背后的点滴.在IDE中,如果我们要开 ...

  6. 把Qt的界面文件(.ui文件)生成源文件(.h或.cpp)封装成链接库

    前言 在用Qt做开发时,为了方便快速,一般都使用Qt设计师界面类来做界面相关的布局,这个类在当前工程中是没有.cpp或.h文件的,但主类又有引入了这个头文件,点开转到定义或声明时,是打不开的,如下图: ...

  7. Qt中ui文件的使用

    Qt(73) 版权声明:本文为博主原创文章,未经博主允许不得转载. 用designer设计的*.ui文件可以通过uic工具转换为*.h文件(在编译时也会自动生成这样一个ui_*.h文件),有了这个.h ...

  8. qt ui界面加入qsplitter_UI 文件设计与运行机制

    上一篇通过一个 "Hello World" 实例,演示了在 Qt Creator 里创建应用程序.设计窗体界面.编译和运行程序的基本过程.这一篇将介绍可视化设计的 UI 界面文件的 ...

  9. 在Qt for Python应用程序中使用Designer UI文件

    在Qt for Python应用程序中使用Designer UI文件 在Qt for Python应用程序中使用Designer UI文件 将表单转换为Python代码 UiTools方法 在Qt f ...

最新文章

  1. ubuntu18.04.4 录制麦克风音频
  2. 我的机器学习入门之路(下)——知识图谱、推荐、广告
  3. r语言x c(-1 -2),【软件】R语言入门之向量
  4. 多数元素—leetcode169
  5. 5G时代探索互动立体视频信息承载的新可能
  6. html5 drawimage 不显示,javascript – 来自视频的HTML5 Canvas drawImage在第一次绘制时不显示...
  7. php soap header_PHP调用有SoapHeader认证的WebService实例
  8. 5V限流IC,0.4A-4.8A可调限流芯片解决方案
  9. 运维基本功(六):Linux用户管理与远程管理
  10. 导出oracle数据库日志文件,Oracle数据库导出还原的两种基本方法imp/impdp
  11. wps如何设置分段页眉
  12. 《灵飞经5·龙生九子》 第二十二章 河咸海淡(上)
  13. CSS3旋转跳跃的立方体
  14. 大话拒绝服务攻击:DoS、DDoS、LDoS——“直男、舔狗和渣男”
  15. 开源 java CMS - FreeCMS2.3 移动app站点配置
  16. VideoCapture,mfc读取视频并使用滚动条
  17. 安卓项目查手机电量功能_Android手机电池详细信息查看
  18. [读后感] 书名:追风筝的人
  19. android 查看文件夹大小 删除文件,Android Base64编码保存本地。查询文件夹大小以及删除...
  20. 关于给hexo博客增加相册页面(实现瀑布流相册,实现加密相册)

热门文章

  1. 毕业之后,生活的压力扑面而来,曾经的梦想也流离失所
  2. 见证奇迹的时刻:让你的头像说话
  3. coupons:美团饿了吗吗外卖红包外卖优惠券,先领红包再下单。外卖红包优惠券,cps分割,别人领红包下单,你拿佣金-源码
  4. C++ 常用WinDef 宏函数LOWORD和HIWORD
  5. Python解决兔子生小宝宝问题
  6. 计算机文化基础在线答题第二次,2017计算机文化基础考试题「附答案」
  7. GP2Y1014AU粉尘传感器模块 PM2.5灰尘传感器代替GP2Y1010AU0F
  8. lin通讯从节点同步间隔场_基于LIN总线的汽车分级制网络结构
  9. 开发经验总结(打造更优秀的日志输出工具类)
  10. 文字转语音哪个软件比较好?