Система ресурсов Qt
Система ресурсов 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 или в одном из его подкаталогов.
Данные ресурсов могут быть скомпилированы в двоичный файл и, таким образом, доступны непосредственно в коде приложения, или двоичный ресурс может быть создан и впоследствии зарегистрирован в системе ресурсов кодом приложения.
По умолчанию, ресурсы доступны в приложении под тем же именем файла, что и в дереве исходного кода, с префиксом :/ или с помощью URL-адреса со схемой qrc.
Например, путь к файлу :/images/cut.png или URL qrc:///images/cut.png обеспечат доступ к файлу cut.png, расположение которого в дереве исходного кода приложения — images/cut.png. Это можно изменить, используя атрибут alias тега file.
<file alias="cut-img.png">images/cut.png</file>
Тогда файл будет доступен как :/cut-img.png в приложении. Также можно указать префикс пути для всех файлов в файле .qrc с помощью атрибута prefix тега qresource:
<qresource prefix="/myresources">
<file alias="cut-img.png">images/cut.png</file>
</qresource> В этом случае файл будет доступен как :/myresources/cut-img.png.
Некоторые ресурсы должны изменяться в зависимости от языка пользователя, например, файлы перевода или значки. Это делается путем добавления атрибута lang к тегу qresource, указав соответствующую строку языка. Например:
<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 для описания формата строк языка.
Внешние двоичные ресурсы
Чтобы создать внешний двоичный ресурс, необходимо создать данные ресурса (обычно с расширением .rcc), передав переключатель -binary в rcc. После создания двоичного ресурса его можно зарегистрировать с помощью API QResource.
Например, набор данных ресурса, указанный в файле .qrc , можно скомпилировать следующим образом:
rcc -binary myresource.qrc -o myresource.rcc
В приложении этот ресурс будет зарегистрирован с помощью такого кода:
QResource::registerResource("/path/to/myresource.rcc"); Встроенные ресурсы
Чтобы ресурс был скомпилирован в двоичный файл, файл .qrc должен быть упомянут в файле .pro приложения, чтобы qmake знал о нём. Например:
RESOURCES = application.qrc
qmake создаст правила make для генерации файла с именем qrc_application.cpp, который будет связан с приложением. Этот файл содержит все данные для изображений и других ресурсов в виде статических массивов C++ сжатых двоичных данных. Файл qrc_application.cpp автоматически пересоздаётся всякий раз, когда изменяется файл .qrc или один из файлов, на которые он ссылается. Если вы не используете файлы .pro, вы можете либо вручную вызвать rcc, либо добавить правила построения в свою систему сборки.
В настоящее время 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() для добавления путей в него.
Использование ресурсов в библиотеке
Если у вас есть ресурсы в библиотеке, вам нужно принудительно инициализировать свои ресурсы, вызвав Q_INIT_RESOURCE() с базовым именем файла .qrc. Например:
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 Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/resources.html