Qt中资源文件的使用及意义

前言

一个应用程序中可能需要加载各种资源(如图标、文本翻译等),对于这些资源的管理,Qt有专门的资源管理系统,它是一个跨平台的资源机制,用于将程序运行时需要的资源以二进制的形式存储到可执行文件内部。因此如果将用到的资源,比如图标文件等,放在资源文件中,它将编译到可执行文件内部,这样就无需担心这些文件的丢失。资源系统基于 qmake、rcc和 QFile 之间的紧密合作。它废弃了 Qt 3的嵌入工具和 image collection 机制。

在内存中,以一棵资源对象树来组织资源。此树在程序启动时被自动生成并且被 QFile 用来定位资源路径。你可以使用带有 ":/" 前缀的 QDir 从根目录开始遍历这棵树。

Qt 资源系统支持搜索路径列表。如果你用 ":" 代替 ":/" 作为前缀,则会使用搜索路径列表来搜索资源。程序启动时搜索路径列表为空,可以用 QDir::addSearchPath() 在其中增加路径。

如果有资源位于静态库中,需要用不带有后缀的 .qrc 文件名为参数调用 Q_INIT_RESOURCE() 来强制初始化资源系统。例如:

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv);
    Q_INIT_RESOURCE(graphlib);
    return app.exec(); 
}

类似地,如果你需要显式地卸载一系列资源(比如插件被卸载或资源不再有效),你可以用同前的文件名为参数调用 Q_CLEANUP_RESOURCE() ,来强制卸载资源。

资源文件

资源文件的后缀名为qrc,它用基于xml的文件格式列出程序所需的文件,其内容示例如下:


   
        image/config-hovered.png
        image/config-normal.png
        image/config-pushed.png
   

   
        load-hovered.png
        load-normal.png
        load-pushed.png
   

注意文件中指明的路径是相对于.qrc文件所在目录的相对路径。而且这些文件必须位于.qrc文件所在的目录或其子目录。

资源文件(qrc文件)有两种使用方式:

一种是通过qmake编译嵌入到应用程序二进制文件中。此时,.qrc 文件必须在 .pro 文件中写明以便于 qmake 可以正确处理。例如:

RESOURCES = application.qrc

qmake 会产生 make 规则来生成一个链接到程序中的名为 qrc_application.cpp 的文件。编译过程如下:

Qt中资源文件的使用及意义_第1张图片

rcc 工具会解析 application.qrc 内的 XML 文本,找到需要添加的各种文件,默认情况下,rcc 工具会对这些文件做 ZIP 压缩,然后将压缩后的 ZIP 数据的每个字节转换成比如 0x6f, 数值形式,所有文件压缩后的数据对应一个 C++ 静态数组 qt_resource_data[] ,并添加注册、取消注册、初始化、清除等函数和资源描述结构体,最终形成一个 qrc_application.cpp 文件。然后用编译器编译 qrc_application.cpp文件,得到 qrc_applicaotion.o ,链接到目标程序内部,就可以用 :/images/copy.png" 等形式访问程序内嵌资源了。每当 qrc_application.cpp 本身或者是其中引用的资源文件发生改变后,该文件都会被自动重新生成。如果你不使用 .pro 文件,那么可以手工调用 rcc 或者在 build 系统中添加 build 规则。

综上,第一种方法是将资源文件内嵌到应用程序中。这对于需要较少资源的程序来说是比较常用的。

而对于太大的图片、音频、视频等文件,就不适合集成到目标程序内部了,这时可以采用第二种方法,即使用qt的RCC工具将资源文件编译成独立的二进制资源(RCC文件)。举例来说,myresource.qrc 包含了很多图片和视频,没法编译成目标程序内嵌资源时,可以打开 Qt 命令行,进入 myresource.qrc 所在的文件夹,执行命令:

rcc -binary myresource.qrc -o myresource.rcc

rcc 会把 myresource.qrc 里面描述的所有图片、视频等文件,都压缩打包,生成一个二进制的 myresource.rcc 文件,这个 myresource.rcc 包含了所有的资源,这样程序发布时就不需要带一堆乱七八糟的碎文件了,一个 myresource.rcc 搞定。

 使用时,在程序中将RCC文件登记到资源系统(使用QResource::registerResource()函数),实现资源的动态加载。

这两种方式的区别是前者在程序执行中,所有的资源都会在内存中,这样尽管读取速度比较快,但也比较占用内存空间(对于只有几个小的图标文件的程序来说就不是问题了),对于内存有限的设备是个问题。而后者可以动态地将资源加载到内存(将资源登记到资源系统)或从内存中清除(通过unregisterResource()反注册)。

默认情况下,程序可以直接使用 ":/" 前缀加与代码树中相同的名字访问资源。例如,:/images/my.png 可以访问在程序代码树中位置为 images/my.png 的 my.png 文件。用文件标签的别名属性(alias)可以改变访问名称,如:

 alias="my.png">images/my.png

之后就可以在程序中使用 :/my.png 访问此文件了。

有些类似于翻译文件和图标的资源可能需要随着用户的本地配置而改变,可以通过为 qresource 标签指明 lang 属性和适当的本地化字符串来完成。例如:

 
my.jpg 
 

my_fr.jpg

如果用户的本地配置是法语(也即 QLocale::system().name() 返回 "fr_FR" ),:/my.jpg 就变成了对 my_fr.jpg 文件的引用。如果是别的本地配置,仍然使用 cut.jpg 。

使用本地化字符串的格式的说明可以参考 QLocale文档。

 

 

如何添加qrc文件

关于如何添加qrc文件,网上有很多相关介绍,此处不再赘述。只需注意:添加到资源文件中的文件必须位于.qrc文件所在的目录或其子目录

 

 

 

你可能感兴趣的:(Qt)