Qt
Qt
目录
.qrc 资源文件
这个机制有点特别,以前没碰到过。好像没相对路径这种东西?需要先添加资源文件,可能和编译机制有关吧
qrc文件
简概
在QtCreator中双击不能打开,需要右击选择打开方式
- Open in Editor,Qt的资源编辑器
- Open with
- 资源编辑器,同Open in Editor
- 文本编辑器,以代码形式打开
- 二进制编辑器,如名
- System Editor,用电脑自带的编辑器
其中文本编辑器打开,代码如下
<RCC>
<qresource prefix="/form"> // 前缀为/from
<file>mainwindow.ui</file> // 该前缀下的资源
</qresource>
</RCC>
优点
底层原理深入解析
参考:
观察
test.qrc 在工程构建后回生成以下两个文件
- qrc_test.cpp
- qrc_test.obj
注意这两个只是编译过程产生的文件,删除不影响程序正常运行。资源已经被嵌入仅exe文件里了
原理
qrc文件
qrc文件本身类似于一个XML格式的文本,用文本编辑器打开则可以看到其XML格式的代码。其记录了所包含的每一个文件的路径
编译过程
关键在于,使用
rcc/pyrcc5/pyside2-rcc
对该文件进行编译时,程序遍历qrc文件里面的每一个文件路径,将该文件的二进制内容写入到相应的输出文件里。
举例(pyside2-rcc编译)
使用的all_day.csv文件是一个纯文本文件,其文件大小为56.4KB;包含该文件路径信息的data.qrc文件大小为85字节;通过pyside2-rcc.exe编译生成的data_rc.py文件大小为70.7KB。(qrc只包含资源路径而不包含文件?)
此外,当我编译完成了data_rc.py之后,即使我删除all_day.csv文件,程序照样能够正常运行并读取all_day.csv里面的数据。除了pyside2-rcc.exe将all_day.csv的所有信息统统写进了编译生成的data_rc.py这种解释外,我实在想不到为什么一个py文件能够达到70.7KB。
qrc文件特性
有了前面的结论,也就很好解释qrc文件的一些相关特性了,例如:
- 目标程序里所有内嵌的资源文件都是只读的,在程序运行时不能修改资源里的文件,只能读取使用。
- 当你修改了qrc资源文件包含的任意文件之后,你必须重复添加-编译的操作才能使更改生效。
- 除了Qt之外的程序想要直接从编译后的文件里面获取信息几乎是不可能的,必须要借助Qt内部接口读取资源文件信息。
rcc 编译工具
RCC 代表 反向 C 编译器(Reverse C Compiler)(不确定)
Qt 自带的开发工具集里有专门的 rcc 工具,用于将 *.qrc 里面描述的图片、文档等编译成对应的源代码文件 qrc_*.cpp 或者独立的二进制资源文件 *.rcc。下面介绍 rcc 工具的两种用途:
- (1) 生成独立的二进制资源文件 *.rcc
- (2) 应用程序内嵌资源
生成独立的二进制资源文件 *.rcc
二进制资源文件 *.rcc
- 对于太大的图片、音频、视频等文件,不适合集成到目标程序内部,可以放到操作系统文件路径,或者单独编译成外挂资源 *.rcc
- myresource.qrc 包含了很多图片和视频,没法编译成目标程序内嵌资源时,可以打包成 rcc文件,操作如下
打包成rcc
打开 Qt 命令行,进入 myresource.qrc 所在的文件夹,执行命令:
rcc -binary myresource.qrc -o myresource.rcc
rcc 会把 myresource.qrc 里面描述的所有图片、视频等文件,都压缩打包,生成一个二进制的 myresource.rcc 文件,这个 myresource.rcc 包含了所有的资源,这样程序发布时就不需要带一堆乱七八糟的碎文件了,一个 myresource.rcc 搞定
使用rcc资源
那么代码中如何使用 myresource.rcc 呢?
需要在 main 函数开始的位置注册这个独立的二进制资源文件
QResource::registerResource("/path/to/myresource.rcc");
然后也是使用之前类似的虚拟文件路径,比如 ":/images/copy.png" 、":/images/cat.gif" 。
应用程序 ”内嵌资源“
内嵌资源
- 比起外挂的二进制资源文件*.rcc,应用程序里面更常见的是内嵌资源,接下来介绍内嵌使用方式
内嵌方法
如果希望一个资源描述文件 application.qrc 在程序编译时内嵌到目标程序里,需要在 *.pro 文件里加一句话:
RESOURCES += application.qrc
qmake 会自动根据这句话,为 application.qrc 添加编译脚本,其编译过程如下
编译流程
图解
![rcc](03.%20.qrc 资源文件.assets/ch05-06-01.png)
文字说明
- (1) rcc 工具会解析 application.qrc 内的 XML 文本,找到需要添加的各种文件,
- (2) 默认情况下,rcc 工具会对这些文件做 ZIP 压缩,然后将压缩后的 ZIP 数据的每个字节转换成比如 0x6f的数值形式,
- (3) 所有文件压缩后的数据对应一个 C++ 静态数组 qt_resource_data[] ,并添加注册、取消注册、初始化、清除等函数和资源描述结构体,
- (4) 最终形成一个 qrc_application.cpp 文件。然后用编译器编译 qrc_application.cpp文件,得到 qrc_applicaotion.o ,链接到目标程序内部,就可以用 ":/images/copy.png" 等形式访问程序内嵌资源了。
qrc_*.cpp 细节
// ... static const unsigned char qt_resource_data[] = { // D:/Project/Dev/Platform/Multi/Qt/Test/UseOfficalQtPlugin/UseOfficalQtPlugin/mainwindow.ui 0x0,0x0,0x3,0xe4, 0x3c, 0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,0x2e, 0x30,0x22,0x20,0x65,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x3d,0x22,0x55,0x54,0x46, 0x2d,0x38,0x22,0x3f,0x3e,0xd,0xa,0x3c,0x75,0x69,0x20,0x76,0x65,0x72,0x73,0x69, 0x6f,0x6e,0x3d,0x22,0x34,0x2e,0x30,0x22,0x3e,0xd,0xa,0x20,0x3c,0x63,0x6c,0x61, // ...这里大概有60多行的0x00的数值形式 0x73,0x6f,0x75,0x72,0x63,0x65,0x73,0x2f,0x3e,0xd,0xa,0x20,0x3c,0x63,0x6f,0x6e, 0x6e,0x65,0x63,0x74,0x69,0x6f,0x6e,0x73,0x2f,0x3e,0xd,0xa,0x3c,0x2f,0x75,0x69, 0x3e,0xd,0xa, }; // ...
其他补充
qmake 为内嵌资源添加的 rcc 编译命令,类似下面这样:
rcc -name application application.qrc -o qrc_application.cpp
应用程序的内嵌资源通常不需要手动初始化,但也有例外情况,比如在使用某些链接库中的资源文件时,如果出现使用了正确的文件路径 ":/images/copy.png" 却找不到资源里图片文件的情况,那么需要在使用该资源的类声明里或者在 main 函数里打头的位置加入一句手动初始化:
Q_INIT_RESOURCE(resources);
,resources 是指 resources.qrc 的简短名字形式,不需要扩展名
使用
添加qrc工程资源
步骤:
- (1) 把文件夹或文件置于项目文件夹中
- (2) 项目管理器中右键 > 点击添加新文件 > Qt > Qt Resource File > 起名配置 会生成一个资源类别的
资源名.qrc
文件 - (3) 右击选择
Open in Editor
的方式打开qrc资源文件并进入编辑界面 - (4) 添加 > 添加前缀(Add Prefix) > 如不添加则填
/
(默认为/new/prefix1
) - (5) 添加 > 添加文件(Add File) > 选择项目文件 需要先添加并选择前缀才能添加文件。可以选多个文件,而不能选文件夹)
- (6) 编译后即可 成功的话项目文件夹中的qrc文件会多出可折叠的资源 且.pro文件会自动附加一行配置:
RESOURCES += \XXX.qrc
使用qrc工程资源
步骤:
- 通用:
: + 前缀名 + 文件名
- 举例:QAction,
ui->actionNew->setIcon(":/source/favicon.ico");
- 举例:QLabel,
ui->qlabel->setPixmap(QPixmap(":/Image/butterfly.png"));
- 举例:QLabel+动图
- (1) 头文件,
#include <QMovie>
- (2) 创建QMovie对象,
QMovie * movie = new QMovie(":/Image/mario.gif");
- (3) 添加到QLabel中,
ui->qlabel->setMovie(movie);
- (4) 播放动图,
movie->start();
- (1) 头文件,
ui界面中使用qrc工程资源,步骤:
- 直接选择就行
使用qrc注意项
- 为了管理方便,需要编译进qrc资源文件的那些文件最好放在.qrc的所在文件夹或者其子文件夹内
- 前缀(prefix)注意项
- 在不加前缀的前提下 在程序中调用同级资源文件可以使用
(":file_name")
如file = QFile(":/all_day.csv")
; 调用子目录资源文件可以用(":path/to/file")
如file = QFile(":/resources/all_day.csv")
。 - 在加前缀的情况下 在程序中调用同级资源文件可以使用
(":/prefix/file_name")
如file = QFile(":/data/all_day.csv")
; 调用子目录资源文件可以用(":/prefix/path/to/file")
如file = QFile(":/data/resources/all_day.csv")
。
- 在不加前缀的前提下 在程序中调用同级资源文件可以使用
- 对于文件大小超过4M的文件,不建议直接编译,而是使用选项
-binary
,具体文档看这里。另外,在Qt的python绑定中不支持-binary
。