Qt资源系统
Qt资源系统是一个平台无关的机制,用于将资源文件与应用程序一起分发。如果您的应用程序始终需要一组特定的文件(如图标、翻译文件、图像),并且不想使用依赖特定系统的打包和定位资源的方式,则可以使用它。
通常,资源文件将嵌入到应用程序的可执行文件中,或者在由应用程序可执行文件加载的库和插件中。另外,资源文件也可以存储在一个外部资源文件中。
资源系统基于Qt的rcc资源编译器、构建系统和Qt运行时API之间的紧密合作。
注意:目前,Qt资源系统不使用任何特定于系统的处理资源的能力,例如Windows、macOS和iOS上的功能。这可能在未来的Qt版本中改变。
Qt资源编译器(rcc)
资源编译器(rcc)命令行工具读取资源文件,并生成一个C++或Python源文件,或者一个.rcc
文件。
文件列表和相关元数据以Qt资源收集文件的形式传递给rcc
。
默认情况下,rcc将生成C++源代码,然后将其编译为可执行文件或库的一部分。使用-g python
选项将生成Python源代码。使用-binary
选项生成一个二进制存档,按照约定保存为.rcc
文件,并可以在运行时加载。
Qt资源收集文件 (.qrc)
.qrc
是一个XML文档,列出了要作为运行时资源包含的本地文件。它作为rcc
的输入。
以下是一个.qrc
文件的示例
<RCC> <qresource prefix="/"> <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>
XML中的每个<file>
元素都标识了应用程序源树中的一个文件。路径相对于包含.qrc
文件的目录解析。
该路径也默认用于在运行时标识文件内容。也就是说,titlebarLeft.png
文件将在资源系统中作为:/res/titlebarLeft.png
或qrc:/res/titlebarLeft.png
可用。要覆盖此默认的运行时名称,请参阅前缀和别名。
Qt Creator、Qt Design Studio、Qt Designer和Qt Visual Studio Tools允许您通过便捷的用户界面创建、检查和编辑.qrc
文件。除了Qt Designer之外,它们还为使用Qt资源系统的项目提供了向导。
构建系统集成
通常在构建应用时处理rcc
资源文件。包括CMake和qmake在内的几个构建工具对此都有专门的支持。
CMake
如果启用了CMAKE_AUTORCC
,您只需将.qrc
文件添加到可执行文件或库的源中。然后,引用的资源文件将被嵌入到二进制中
set(CMAKE_AUTORCC ON) qt_add_executable(my_app application.qrc main.cpp )
有关AUTORCC的更多详细信息,请参阅CMake的AUTORCC文档。
AUTORCC的替代方案是使用Qt6Core的CMake函数qt_add_resources,这提供了对创建资源的更多控制。例如,它允许您在项目文件中直接指定资源内容,而无需先编写.qrc
文件
qt_add_resources(my_app "app_images" PREFIX "/" FILES images/copy.png images/cut.png images/new.png images/open.png images/paste.png images/save.png )
最后,qt_add_qml_module允许您将Qt Quick资源嵌入到应用程序的资源系统中。该函数定义在Qt6 CMake包的Qml
组件中。
qmake
qmake支持使用RESOURCES
变量处理资源。如果您将.qrc
文件路径添加到变量中,则列出的资源文件将被嵌入到生成的库或可执行文件中
RESOURCES = application.qrc
这创建了包含几个.png
文件的资源,可通过以下方式访问:":/res/titlebarLeft.png"
。
如果要将文件嵌入资源中的目录布局与应用程序的预期不匹配,您可以指定resources.base
。其中,base
是表示文件别名根点的路径前缀。在上例中,如果resources.base
设置为"res"
,则titlebarLeft.png
可通过以下方式访问:":/titlebarLeft.png"
。
运行时API
Qt API处理迭代和读取文件的接口具有内置的对Qt资源系统的支持。您可以将资源路径传递给QFile和QDir,也可以传递给例如QIcon、QImage和QPixmap构造函数
使用:
前缀明确指出"/images/cut.png"应从Qt资源系统中加载。
您还可以通过QUrl引用Qt资源系统。在这种情况下,请使用qrc
方案
QQmlApplicationEngine engine; engine.load(QUrl("qrc:/myapp/main.qml"));
高级主题
前缀
一个.qrc
文件可以设置一个前缀,用于添加到<file>
元素中给出的每个本地文件名,以便通过资源系统中应使用的名称来获取该文件
前缀允许您对资源进行结构化,避免不同库或插件中通过不同.qrc
文件添加的资源文件之间发生冲突。
注意:前缀qt.conf文件在代码中的查找通常是在:/qt/etc/qt.conf
或qrc:/qt/etc/qt.conf
中。
别名
有时在运行时让资源文件可用在不同路径下是很方便的。通过设置 alias
属性,.qrc
文件允许这样做。
<file alias="cut-img.png">images/cut.png</file>
如果文件来自应用程序,那么它只能以 :/cut-img.png
或 qrc:/cut-img.png
的形式访问。
忽略文件内容
有时你想将文件节点添加到资源文件系统中,但实际上不希望添加文件内容。通过将 empty
属性设置为 true
,.qrc
文件允许这样做。
<file empty="true">Button.qml</file>
生成的文件仍然可以从应用程序中访问,但内容为空。
这对于从应用程序二进制文件中删除 QML 源代码很有用。
注意:如果你从二进制文件中省略 QML 源代码,QML 引擎必须依赖于由 qmlcachegen 或 qmlsc 创建的编译单元。这些与构建它们的 Qt 的特定版本相关联。如果你更改应用程序使用的 Qt 版本,它们将无法再加载。
语言选择器
一些资源需要根据用户的地区进行更改,例如翻译文件或图标。资源集合文件 通过给 qresource
标签添加 lang
属性来支持此功能,指定一个合适的地区字符串。例如
<qresource> <file>cut.jpg</file> </qresource> <qresource lang="fr"> <file alias="cut.jpg">cut_fr.jpg</file> </qresource>
如果用户的地区是法语(例如,QLocale::system() 的语言是法语),:/cut.jpg
或 qrc:/cut.jpg
将成为指向 cut_fr.jpg
图像的引用。对于其他地区,使用 cut.jpg
。
有关地区字符串使用的格式说明,请参阅 QLocale 文档。
有关选择特定地区资源的功能,请参阅 QFileSelector。
嵌入大型文件
默认情况下,rcc
将资源文件以 C++ 数组的形式嵌入到可执行文件中。这对于大型资源来说可能会出现问题。
如果编译器花费的时间太长,或者因为内存溢出而失败,你可以选择进入一种特殊模式,其中资源作为两步过程的一部分进行嵌入。C++ 编译器只为资源在目标可执行文件或库中预留足够的空间。然后在编译和链接阶段之后,通过另一个 rcc 调用来完成资源文件的内容和元数据的实际嵌入。
对于 CMake,你需要使用 qt_add_big_resources 函数。
外部资源文件
将资源文件嵌入到二进制文件的替代方法是将其存储在一个单独的 .rcc
文件中。使用 -binary
选项,rcc
允许这样做。这样一个 .rcc
文件然后在运行时通过 QResource 加载。
例如,通过以下方式编译在 .qrc
文件中指定的资源数据集
rcc -binary myresource.qrc -o myresource.rcc
在应用程序中,可以使用以下代码注册此资源
QResource::registerResource("/path/to/myresource.rcc");
如果你使用 CMake,可以使用 qt_add_binary_resources 函数来安排上面的 rcc
调用
qt_add_binary_resources(resources application.qrc DESTINATION application.rcc) add_dependencies(my_app resources)
Qt for Python应用程序中的资源
资源收集文件通过资源编译器rcc转换为Python模块
rcc -g python mainwindow.qrc > mainwindow_rc.py
然后可以在应用程序中导入此模块
import mainwindow_rc.py
压缩
rcc
尝试压缩内容以优化最终可执行文件的磁盘空间使用。默认情况下,它将执行启发式检查以确定压缩是否值得,如果未能充分压缩,则会存储内容为未压缩格式。要控制阈值,可以使用-threshold
选项,该选项告诉rcc
必须达到原始文件大小的百分比才能将其存储为压缩格式。
rcc -threshold 25 myresources.qrc
默认值为"70",表示压缩文件必须比原始文件小70%(即原始文件大小的最多30%)。
如果需要,可以关闭压缩。如果你已经使用压缩格式存储资源,如.png
文件,并且不想在构建时消耗CPU成本以确认无法压缩,这会有所帮助。另一个原因是如果磁盘使用不是问题,并且应用程序希望保持内容在运行时作为干净内存页面。您可以通过提供-no-compress
命令行参数来完成此操作。
rcc -no-compress myresources.qrc
rcc
还让您可以控制压缩级别和压缩算法,例如
rcc -compress 2 -compress-algo zlib myresources.qrc
也可以将threshold
、compress
和compress-algo
作为.qrc file
标签的属性使用。
<qresource> <file compress="1" compress-algo="zstd">data.txt</file> </qresource>
上述内容将选择压缩级别为1的zstd
算法。
rcc
支持以下压缩算法和压缩级别
best
:使用以下算法中最佳的算法,在最高的压缩级别上使用,以实现最大的压缩,代价是在编译过程中消耗大量CPU时间。此值在XML文件中用于指示文件应尽可能压缩,不论rcc
支持哪些算法。zstd
:使用Zstandard库压缩内容。有效的压缩级别从1到19,1表示最少的压缩(最少的CPU时间),19表示最多的压缩(最多的CPU时间)。默认级别是14。特殊值0告知zstd
库选择实现定义的默认值。zlib
:使用zlib库压缩内容。有效的压缩级别从1到9,1应用最少的压缩(最少的CPU时间),9应用最多的压缩(最多的CPU时间)。特殊值0表示“不压缩”,不应使用。默认值是实施定义的,但通常是级别6。none
:不压缩。这与-no-compress
选项相同。
对Zstandard和zlib的支持是可选的。如果在编译时没有检测到给定的库,尝试传递该库的-compress-algo
将导致错误。如果启用了压缩算法,默认压缩算法是zstd
,如果没有启用,则是zlib
。
显式加载和卸载嵌入资源
嵌入到C++可执行文件或库代码中的资源将自动在内部全局变量的构造函数中注册到Qt资源系统中。由于全局变量在main()运行之前就初始化了,因此资源在程序启动时可用。
在将资源嵌入到静态库中时,C++链接器可能会删除注册资源的静态变量。因此,如果您在静态库中嵌入资源,您需要通过调用 Q_INIT_RESOURCE() 并使用 .qrc
文件的基名来显式注册您的资源。例如
MyClass::MyClass() : BaseClass() { Q_INIT_RESOURCE(resources); QFile file(":/myfile.dat"); ... }
您还可以显式地从应用程序中删除已注册的资源,例如在卸载插件时。为此请使用 Q_CLEANUP_RESOURCE()。
注意:由于由rcc生成的资源初始化器在全局命名空间中声明,您调用 Q_INIT_RESOURCE() 和 Q_CLEANUP_RESOURCE() 需要在任何命名空间外部完成。
© 2024 The Qt Company Ltd. 本文档贡献的版权为各自所有者的版权。本提供的文档是依据自由软件基金会发布的 GNU自由文档许可证版本1.3 条款许可的。Qt及其相应标志是芬兰和其他国家/地区的 The Qt Company Ltd. 的商标。所有其他商标均为其各自所有者的财产。