目录
Qt 资源系统
Qt 资源系统是一种与平台无关的机制,用于存储应用程序的可执行的二进制文件。如果您的应用程序总是需要使用一组特定的文件(图标,翻译文件等),并且您不想冒丢失文件的风险,这将会很有用。
资源系统基于qmake,rcc(Qt的资源编译器)和QFile之间的紧密合作。
资源收集文件(.qrc)
与应用程序相关联的资源在.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 shceme 的URL。【译者注:即可以有两种方式访问,一种是文件路径形式,另一种是 URL 地址形式。URL形式用在传入的参数为 QUrl 类】
例如,使用文件路径形式“:/images/cut.png" 或 URL形式 "qrc:///images/cut.png " 可以访问 cut.png 文件,该文件在应用程序源代码树中的位置为 images / cut.png。【译者注:即前文中 .qrc 文件的示例中所示】。 可以使用 file 标签的 alias 属性更改访问名称:
<file alias="cut-img.png">images/cut.png</file>
然后,可以在应用程序中以:/cut-img.png 格式访问该文件。 也可以使用 qresource 标签的 prefix 属性为.qrc文件中的所有文件指定路径前缀:
<qresource prefix="/myresources">
<file alias="cut-img.png">images/cut.png</file>
</qresource>
在这种情况下,可以通过":/myresources/cut-img.png "访问该文件。
【译者注:未设置 prefix 或 prefix 为 “/”,其访问文件的方式是一样的。】
有些资源需要根据用户的语言环境进行更改,例如:翻译文件、图标。 这种情况下,可通过为 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 扩展名)。【译者注:扩展名也可以不是 .rcc,而是任意的其它自定义的字符串,如 .tc】。 创建二进制资源后,可以使用 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,macOS和iOS 上,操作系统也提供对资源的原生支持。 这可能会在将来的 Qt 版本中更改。
压缩
默认情况下,资源是会被压缩的(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() 来强制初始化资源系统。 例如:
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()。