Qt 资源系统是一种独立于平台的机制,用于在应用程序的可执行文件中存储二进制文件。如果应用程序始终需要一组特定的文件(图标、翻译文件等)并且不想冒丢失文件的风险,这将非常有用。
资源系统基于构建系统、rcc(Qt 的资源编译器)和 QFile 之间的紧密合作。
与应用程序关联的资源在 *.qrc 文件中指定,这是一种基于 XML 的文件格式,它列出磁盘上的文件,并可选择为它们分配一个资源名称,应用程序必须使用该名称来访问资源。
这是一个示例 .qrc 文件:
images/copy.png
images/cut.png
images/new.png
images/open.png
images/paste.png
images/save.png
*.qrc 文件中列出的资源文件是应用程序源代码树的一部分。指定的路径相对于包含 .qrc 文件的目录。
资源数据可以编译成二进制文件,从而在应用程序代码中立即访问,或者可以创建二进制资源,然后在应用程序代码中注册到资源系统。
默认情况下,资源可以在应用程序中访问,文件名与它们在资源树中的文件名相同,带有 :/ 前缀,或者通过带有 qrc 格式的 URL。
例如,文件路径 :/images/cut.png 或 URL qrc:///images/cut.png 将提供对 cut.png 文件的访问权限,该文件在应用程序源树中的位置为 images/cut.png。 这可以使用文件标签的别名属性进行更改:
images/cut.png
然后可以从应用程序以 :/cut-img.png 的形式访问该文件。也可以使用 qresource 标记的前缀属性为 .qrc 文件中的所有文件指定路径前缀:
images/cut.png
在这种情况下,该文件可作为 :/myresources/cut-img.png 访问。
某些资源需要根据用户的区域设置进行更改,例如翻译文件或图标。这是通过向 qresource 标记添加 lang 属性,指定合适的语言环境字符串来完成的。 例如:
cut.jpg
cut_zh.jpg
如果用户的语言环境是汉语(即 QLocale::system().name() 返回“zh_CN”),:/cut.jpg 为cut_zh.jpg 图像的引用。对于其他语言环境,:/cut.jpg 为 cut.jpg。
对于要创建的外部二进制资源,必须使用 rcc(资源编译器 ) 来创建资源数据(通常使用 .rcc 扩展名)。 创建二进制资源后,可以使用 QResource API 注册资源。
例如,.qrc 文件中指定的一组资源数据可以通过以下方式进行编译:
rcc -binary myresource.qrc -o myresource.rcc
在应用程序中,此资源将使用如下代码注册:
QResource::registerResource("/path/to/myresource.rcc");
对于要编译为二进制文件的资源,必须在应用程序的项目文件中提及 .qrc 文件,以便构建工具知道它。
在 qmake 项目中,将 .qrc 文件分配给 RESOURCES 变量:
RESOURCES = application.qrc
qmake 将生成 make 规则以生成一个名为 qrc_application.cpp 的文件,该文件链接到应用程序中。该文件包含图像和其他资源的所有数据,作为压缩二进制数据的静态 C++ 数组。 qrc_application.cpp 文件在 .qrc 文件更改或其引用的文件之一发生更改时自动重新生成。
使用资源编译器 rcc 将资源集合文件转换为 Python 模块:
rcc -g python application.qrc > application_rc.py
该模块需要在应用程序中导入:
import application_rc.py
在应用程序中,大部分地方都可以使用资源路径,而不是普通的文件系统路径。特别是,可以将资源路径而不是文件名传递给 QIcon、QImage 或 QPixmap 构造函数:
cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
在内存中,资源由资源对象树表示。 该树在启动时自动构建,并由 QFile 用于解析资源路径。可以使用以 “:/” 初始化的 QDir 从根目录浏览资源树。
Qt 的资源支持搜索路径列表的概念。如果随后使用 : 而不是 :/ 作为前缀来引用资源,则将使用搜索路径列表查找该资源。
如果库中有资源,则需要通过使用 .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():
rcc 尝试压缩内容以优化最终二进制文件中的磁盘空间使用。默认情况下,如果未充分压缩,它将存储未压缩的内容。要控制阈值,可以使用 -threshold 选项,该选项告诉 rcc 必须获得原始文件大小的百分比才能以压缩形式存储文件。
rcc -threshold 25 myresources.qrc
默认值为“70”,表示压缩后的文件必须比原文件小70%(不超过原文件大小的30%)。
如果需要,可以关闭压缩。以下情况可以关闭:
可以通过提供 -no-compress 命令行参数来完成此操作。
rcc -no-compress myresources.qrc