简述

Qt 的资源系统用于存储应用程序的可执行二进制文件,它采用平台无关的机制。当你的程序总需要这样的一系列文件(图标、翻译文件等)并且不想冒丢失某些文件的风险时,这就显得十分有用。

资源系统基于 qmake、rcc(Qt 资源编译器) 和 QFile 之间的紧密合作。

资源集合文件(.qrc)

与程序相关的资源在被指定在一个 .qrc 文件中,其基于 XML 的文件格式列出了磁盘上的文件,可以为它们指定一个应用程序访问资源时必须使用的资源名称。

下面是一个 .qrc 文件的示例:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

.qrc 文件中列出的资源文件是程序代码树中的一部分。指定的路径相对于 .qrc 文件所在目录。注意:列出的资源文件必须位于 .qrc 文件所在目录或其子目录。

资源数据可以编译成二进制,进而在程序代码中立即访问;或者创建一个二进制资源,在晚些时候用资源系统来注册程序代码。

默认情况下,程序可以使用与代码树中相同的名字访问资源,需要带有 “:/” 前缀,或者有qrc scheme的URL。

例如: :/images/cut.png 或者URL qrc:///images/cut.png 都可以访问在程序代码树中位置为 images/cut.png 的 cut.png 文件。用文件标签的别名属性可以改变访问名称:

<file alias="cut-img.png">images/cut.png</file>

之后,在程序中就可以使用 :/cut-img.png 访问此文件了。还可以使用 qresource 标签的前缀属性为 .qrc 文件中列出的所有文件指定路径前缀:

<qresource prefix="/myresources">
<file alias="cut-img.png">images/cut.png</file>
</qresource>

这种情况下,就可以使用 :/myresources/cut-img.png 访问该文件了。

有些资源可能需要随着用户本地的配置而改变,例如:翻译文件、图标,可以通过为 qresource 标签添加一个 lang 属性,并指定一个适当的本地字符串来完成。例如:

<qresource>
<file>cut.jpg</file>
</qresource>
<qresource lang="fr">
<file alias="cut.jpg">cut_fr.jpg</file>
</qresource>

如果用户的语言是法语(即:QLocale::system().name() 返回“fr_FR”),:/cut.jpg 就变成了对 cut_fr.jpg 文件的引用。如果是其它语言,仍然使用 cut.jpg 。

使用语言字符串的格式的说明可以参考 QLocale 文档。

外部二进制资源

要创建外部二进制资源,必须通过传递 -binary 给 rcc 来创建资源数据(通常使用 .rcc 扩展名),一旦二进制资源被创建,就可以使用 QResource API 注册该资源。

例如, .qrc 文件中指定的一系列资源数据可以用下面的方式编译:

rcc -binary myresource.qrc -o myresource.rcc

在程序里,需要用以下代码注册该资源:

QResource::registerResource("/path/to/myresource.rcc");

内编译资源

要把一个资源编译到二进制文件中, 必须在 .pro 中明确指定.qrc 文件,以便于 qmake 可以正确处理。例如:

RESOURCES     = application.qrc

qmake 会产生 make 规则来生成一个链接到程序中的名为 qrc_application.cpp 的文件。这个文件以静态的 C++ 压缩二进制数组包含了所有图片和其它资源的数据。当 qrc_application.cpp 本身或者是其引用的资源文件发生改变后,该文件都会被自动重新生成。如果你不使用 .pro 文件,那么可以手工调用 rcc 或者为 build 系统添加 build 规则。

目前,Qt 总是把资源数据存储在可执行文件中,甚至是在 Windows、Mac OS X 和 iOS 这些原生支持资源机制的操作系统中。在将来的 Qt release 版本中可能会改变。

压缩

默认情况下,资源是被压缩的(ZIP 格式),也可以关闭压缩。如果你的资源已经包含了一个压缩格式(例如: .png 文件),这可能会比较有用。可以通过命令行传递 -no-compress 来指定:

rcc -no-compress myresources.qrc

rcc 也在压缩上给你提供了一些控制,当压缩文件时,可以指定压缩级别和阈值水平时,例如:

rcc -compress 2 -threshold 3 myresources.qrc

在程序中使用资源

在程序中,资源路径在大多数情况可以代替一般的文件系统路径。特别是,可以用资源路径取代文件名传递给 QIcon、 QImage ,或者 QPixmap 的构造函数:

cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);

可以参考 Application 示例,了解更多关于应用程序使用 Qt 资源系统来存储图标的内容。

在内存中,资源由一个资源对象树来表示。此树在程序启动时被自动生成,并被 QFile 用来解析路径到资源。你可以使用带有 “:/” 前缀的 QDir 从根目录开始遍历这棵树。

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

如果有资源位于静态库中,需要用不带有后缀的 .qrc 文件名为参数调用 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() 与上面相同的基本名称。

注意:当资源被构建为应用程序的一部分时,没有必要使用 Q_INIT_RESOURCE() 和Q_CLEANUP_RESOURCE()。

更多参考

  • The Qt Resource System - Qt 助手

Qt之资源系统的更多相关文章

  1. Qt:Qt资源系统

    学习自 Qt 资源系统(Qt Resource System) - 知乎 1.什么是Qt 资源系统 Qt资源系统是一种将图片.数据存储于二进制文件中的一套系统.这些图片.数据会被我们的程序使用,它们称 ...

  2. QT中自定义系统托盘的实现—c++语言为例

    将要介绍的是:QT中自定义系统托盘(systemtray)的一个Demo,希望能帮需要的读者快速上手. 前提假设是诸位已经知道QT中的signals .slot以及资源文件,所以关于这些不会再累述. ...

  3. 学习Qt的资源-网站、论坛、博客等

    来自<零基础学Qt 4编程>一书的附录 附录C Qt资源 C.1 Qt 官方资源 全球各大公司以及独立开发人员每天都在加入 Qt 的开发社区.他们已经认识到了Qt 的架构本身便可加快应用程 ...

  4. 【转载】分享一些Qt学习资源,欢迎下载

    资源来源:http://bbs.csdn.net/topics/390358737 经过我一翻整理,把一些我收集到的Qt学习资源分享给大家,主要适合新手,老鸟可以直接忽略我.要说明一下,很多资源都是在 ...

  5. ylbtech-dbs:ylbtech-3,BarCode(条码资源系统)

    ylbtech-dbs:ylbtech-3,BarCode(条码资源系统) -- =============================================-- 条码资源系统-- YU ...

  6. QT的Paint 系统

    下面对于QT的绘制系统做一个简要说明, 这个系统主要由三部分组成,  QPainter, QPaintDevice, QPaintEngine. QPainter 是一个绘制接口类,提供绘制各种面向用 ...

  7. QT下资源使用和资源占用…(可以动态加载资源文件,这样不占内存)

    原文地址:关于QT下资源使用和资源占用内存过多的问题作者:技术成就梦想     最近研究了一下如何从外部动态调用图片的问题,从而研究了图片资源的使用方法.网上最常见的帖子是这个,感觉总结的还不错. h ...

  8. 关于QT下资源使用和资源占用…

    原文地址:关于QT下资源使用和资源占用内存过多的问题作者:技术成就梦想     最近研究了一下如何从外部动态调用图片的问题,从而研究了图片资源的使用方法.网上最常见的帖子是这个,感觉总结的还不错. h ...

  9. 解析Qt元对象系统(五) Q_INVOKABLE与invokeMethod(automatic connection从Qt4.8开始的解释已经与之前不同,发送对象驻足于哪一个线程并不重要,起到决定作用的是接收者对象所驻足的线程以及发射信号(该信号与接受者连接)的线程是不是在同一个线程)good

    概述查看Qt源码可知,Q_INVOKABLE是个空宏,目的在于让moc识别. 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起. Q_INVOKABLE与QMe ...

随机推荐

  1. C#闪屏

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  2. Debug不崩溃Release版本崩溃的一种原因

    今天有一个工程Debug是正常,Release崩溃,郁闷至极. 研究了一下下午,原因是一个类成员变量没有构造函数中初始化.而Debug版本正好没有问题. 所以定义类成员,一定不能忘记初始化!!

  3. 面向对象--类库、委托、is和as运算符、泛型集合

    类库: 其实就是一堆类文件,只是看不到这些类的源代码,保密性好. 优点:保密性好 缺点:如果这个方法不好用,使用者无法自己去更改它. 给的大多是dll文件.使用方法:引用右键,添加引用,浏览,选择到相 ...

  4. liftover的使用/用法

    Lift genome positions Genome positions are best represented in BED format. UCSC provides tools to co ...

  5. [HDOJ3714]Error Curves(三分)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3714 题意:求n个二次函数在[0,1000]的最小值. 三分枚举. #include <bits ...

  6. [转]Socket send函数和recv函数详解

    1.send 函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP ...

  7. QT 加载c语言编译的动态库

    QLibrary lib("./libprint.so");//库的路径if(lib.load()){    typedef void(*AddFunction)(char *st ...

  8. centos vpn

    yum install ppp -y cd /usr/local/src wget http://dl.fedoraproject.org/pub/epel/7/x86_64/p/pptpd-1.4. ...

  9. Entity Framework 学习初级篇--基本操作:增加、更新、删除、事务(转)

    摘自:http://www.cnblogs.com/xray2005/archive/2009/05/17/1458568.html 本节,直接写通过代码来学习.这些基本操作都比较简单,与这些基本操作 ...

  10. C#正则表达式编程(三):Match类和Group类用法

    前面两篇讲述了正则表达式的基础和一些简单的例子,这篇将稍微深入一点探讨一下正则表达式分组,在.NET中正则表达式分组是用Match类来代表的.首先先看一段代码: /// <summary> ...