Система ресурсов 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/qt-5.9/resources.html