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