Qt资源系统,再也不用担心按钮图标不见了

描述

一、资源系统

Qt的资源系统是一种独立于平台的机制,目的是用于在应用程序的可执行文件中存储二进制文件。资源系统基于qmake、Qt的资源编译器(rcc)和QFile实现。如果应用程序总是需要一组特定的文件(例如图标、翻译文件等),并且不想让这些文件丢失而影响应用程序的功能,这时候则可以使用Qt资源系统解决这个问题。

二、外部二进制文件

Qt对于外部的二进制文件,如果需要使用这个二进制文件,那么则必须将所需要使用的二进制文件转换成Qt的资源数据文件(默认文件名后缀为.rcc)。转换步骤如下:

在Windows命令行下(这里以Windows系统为例),输入以下命令:

编译器

备注:这里windows命令行工作区目录需要切换到.qrc文件所在的文件夹下,如上,笔者的工程项目的.qrc文件位于上述文件路径。然后再输入上述命令,便可使用rcc工具生成对应的资源文件。如下图:

编译器

上图所示目录下的rc.rcc则是生成的资源文件。资源文件生成完成后,如何在应用程序中使用呢?

(1)在应用程序中使用registerResource()注册资源,如下代码:

 

#include "widget.h"

#include 
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    //资源文件的路径
    QString rccPath = "C:/Users/iriczhao/Documents/untitled6/rc.rcc";
 
    //注册资源文件
    if(!QResource::registerResource(rccPath))
    {
        qDebug()<<"rcc register failed!";
    }

    Widget w;
    w.show();
    
    return a.exec();
}

 

(2)默认情况下,在应用程序中,可以使用与资源树中相同的文件名访问资源,使用 :/ 前缀,或者使用qrc模式的URL访问资源。例如,文件路径:/images/top_bk.png或URL qrc:///images/top_bk.png将提供对top_bk.png文件的访问,该文件在应用程序资源树中的位置是images/top_bk.png。

如果不需要资源文件了,可以使用unregisterResource()卸载注册的资源。

本小节描述的资源文件使用方法是:rcc+QResource。这种方式在发布应用软件时需要连资源文件一起发布,并且需要保证资源的路径与应用程序中设置的一致。除了这种方式,还可以将资源与应用程序编译成二进制文件,后文会继续写到。

在内存中,资源由资源对象树表示,该树在启动时自动构建,并由QFile解析资源的路径。我们可以使用:/初始化的QDir从资源树根开始地方进行资源导航和搜索。Qt的资源系统支持搜索路径列表,如果使用:而不是:/作为前缀引用资源,则将使用搜索路径列表查找该资源。搜索路径列表在启动时为空;需要调用QDir::addSearchPath()添加资源搜索路径。

三、将资源与应用程序编译成二进制文件

方法如下:

在工程文件.pro中,新增RESOURCES变量,如下:

 

RESOURCES =  application.qrc

 

application.qrc为资源描述文件。还可以通过QtCreator的资源创建对话框添加。

这样在应用程序构建中,资源文件将会与应用程序一起构建成统一的整体,如下图所示:

编译器

通过这种方式,Qt总是将资源数据与应用程序编译构建在一起。这样就不必担心丢失资源的问题,但是会为需要编译的资源开设内存空间,对硬件资源严苛的环境并不友好。

四、使用库中的资源

如果资源在库中,若需要使用库中资源,则需要调用Q_INIT_RESOURCE()强制初始化资源,将.qrc文件的资源名传入到Q_INIT_RESOURCE()中。例如:

 

MyClass::MyClass() : BaseClass(){
    Q_INIT_RESOURCE(resources); //强制初始化资源

    QFile file(":/myfile.dat");
...
}

 

这种方式确保了在静态链接的情况下,资源被链接到最终的应用程序二进制文件中。在实际开发中,应该将初始化代码放在库中使用资源的位置附近,这样,如果基于库的应用程序使用了依赖于它们的库的特性,那么它们将只链接这些资源。

注意:由于rcc生成的资源初始化器是在全局名称空间中声明的,所以对Q_INIT_RESOURCE()的调用也需要在名称空间之外进行。

如果库包含的资源不是内部使用的,而是公开给库的应用程序端,则需要在应用程序代码中进行初始化。例如:

 

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

    QFile file(":/graph.png");
    ...
 return app.exec();
}

 

这可以确保在静态链接的情况下将资源链接到最终的应用程序二进制文件中,但在动态链接的情况下(如插件)也会触发库加载。

同样,如果必须显式卸载一组资源,可以调用Q_CLEANUP_RESOURCE()来强制删除资源,传入的参数是.qrc资源文件名称。

注意:当资源作为应用程序的一部分构建时,Q_INIT_RESOURCE()和Q_CLEANUP_RESOURCE()是不必要的。

五、资源压缩

Qt资源压缩是指:利用Qt的资源编译器(rcc)对资源文件(.qrc)中提到的资源进行压缩处理,以此方式优化最终二进制文件占用磁盘空间的情况 。默认情况下,它将执行自发式检查,以确定压缩是否值得,如果压缩不够,它将存储未压缩的内容。Qt资源文件的压缩有如下特点:

(1)可以设置压缩的压缩阈值(threshold)。

(2)可以打开或关闭压缩功能。

(3)可以设置压缩等级。

(4)rcc支持以下压缩算法和压缩等级:

序号 压缩方式 描述
1 zstd 使用Zstandard库来压缩内容。有效的压缩级别范围从1到19,1是最小的压缩(耗费最少的CPU时间),19是最大的压缩(耗费最多的CPU时间)。默认级别为14。特殊值0告诉zstd库选择一个实现定义的默认值。
2 zlib 使用zlib库压缩内容。有效的压缩级别范围从1到9,1是应用最少的压缩(耗费最少的CPU时间),9是应用最多的压缩(耗费最多的CPU时间)。特殊值0表示“不压缩”,实际开发中不应使用。默认通常是级别6。
3 none 没有压缩。与-no-compress选项相同。

六、总结

总而言之,Qt框架对应用程序的资源有两种使用、控制方式:

(1)第一种是直接将资源(如图片、图表)等与应用程序一起构建编译,通过这种方式,资源数据将会与应用程序成为整体,不用担心资源数据的丢失问题,但是对于内存资源严苛的环境并不友好。

(2)第二种是通过QResource类API动态的注册和卸载资源数据文件(也称为动态资源引入)。这样在程序的运行中能动态的加载、引入资源数据,便于资源数据的管理和使用,同时也缩小了应用程序的内存占用空间。在Qt框架中,使用的外部资源文件(二进制)必须是.rcc文件。这种文件需要使用Qt资源编译器(RCC)工具进行编译、处理、生成,然后使用QResource类进行.rcc文件的注册和卸载操作,动态的在应用程序运行过程中使用资源文件。

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分