Рекомендации по использованию QML и Qt Quick
Несмотря на все преимущества, которые предоставляют QML и Qt Quick, в некоторых ситуациях они могут быть сложными. В следующих разделах подробно описаны некоторые рекомендации, которые помогут вам получить лучшие результаты при разработке приложений.
Пользовательские элементы управления UI
Гибкий и современный интерфейс пользователя (UI) является ключевым фактором успеха любого приложения в современном мире, и именно здесь QML так подходит для дизайнеров или разработчиков. Qt предлагает наиболее базовые элементы управления UI, необходимые для создания гибкого и стильного интерфейса. Рекомендуется ознакомиться с этим списком элементов управления UI перед созданием собственного пользовательского элемента управления.
Помимо этих базовых элементов управления UI, которые предоставляет сам Qt Quick, также доступен богатый набор элементов управления UI с Qt Quick Controls 2. Они отвечают на самые распространённые случаи использования без каких-либо изменений и предлагают гораздо больше возможностей с помощью опций настройки. В частности, Qt Quick Controls 2 предоставляет параметры стилизации, которые соответствуют последним тенденциям в дизайне UI. Если эти элементы управления UI не удовлетворяют потребности вашего приложения, только тогда рекомендуется создавать пользовательский элемент управления.
Связанная информация
Рекомендации по кодированию
См. Рекомендации по кодированию QML.
Архивирование ресурсов приложения
Большинство приложений зависят от ресурсов, таких как изображения и значки, для обеспечения богатого пользовательского опыта. Часто может быть сложно сделать эти ресурсы доступными для приложения независимо от целевой операционной системы. Большинство популярных ОС используют более строгие политику безопасности, которая ограничивает доступ к файловой системе, что затрудняет загрузку этих ресурсов. В качестве альтернативы Qt предлагает собственную систему ресурсов, встроенную в исполняемый файл приложения, обеспечивающую доступ к ресурсам приложения независимо от целевой ОС.
Например, рассмотрите следующую структуру каталогов проекта:
project
├── images
│ ├── image1.png
│ └── image2.png
├── project.pro
└── qml
└── main.qml Следующая запись в project.pro гарантирует, что ресурсы будут включены в исполняемый файл приложения, делая их доступными при необходимости:
RESOURCES += \
qml/main.qml \
images/image1.png \
images/image2.png Более удобный подход — использование синтаксиса подстановочных символов wildcard для выбора нескольких файлов сразу:
RESOURCES += \
$$files(qml/*.qml) \
$$files(images/*.png) Этот подход удобен для приложений, зависящих от ограниченного числа ресурсов. Однако всякий раз, когда к RESOURCES добавляется новый файл с этим подходом, все другие файлы в RESOURCES также перекомпилируются. Это может быть неэффективно, особенно для больших наборов файлов. В этом случае лучший подход — разделить каждый тип ресурсов в свой собственный файл .qrc. Например, фрагмент кода выше можно изменить на следующее:
qml.files = $$files(*.qml) qml.prefix = /qml RESOURCES += qml images.files = $$files(*.png) images.prefix = /images RESOURCES += images
Теперь при изменении файла QML перекомпилируются только файлы QML.
Иногда может потребоваться больше контроля над путём для определённого файла, управляемого системой ресурсов. Например, если мы хотим дать image2.png псевдоним, нам нужно переключиться на явное указание .qrc файла. Создание файлов ресурсов подробно объясняет, как это сделать.
Связанная информация
Разделение интерфейса от логики
Одна из основных целей большинства разработчиков приложений — создание поддерживаемого приложения. Один из способов достижения этой цели — разделение пользовательского интерфейса (UI) от бизнес-логики. Ниже приведены несколько причин, почему UI приложения следует писать на QML:
- Декларативные языки идеально подходят для определения UI.
- Код QML проще писать, так как он менее подробный, чем C++, и не является строго типизированным. Это также делает его отличным языком для прототипирования, качество, которое является жизненно важным при сотрудничестве с дизайнерами, например.
- JavaScript легко используется в QML для реагирования на события.
Являясь строго типизированным языком, C++ лучше всего подходит для логики приложения. Как правило, такой код выполняет задачи, такие как сложные вычисления или обработка данных, которые быстрее выполняются на C++, чем на QML.
Qt предлагает различные подходы к интеграции кода QML и C++ в приложении. Типичный пример — отображение списка данных в пользовательском интерфейсе. Если набор данных статичен, прост и/или мал, модели, написанные на QML, могут быть достаточными.
Следующий фрагмент кода демонстрирует примеры моделей, написанных на QML:
model: ListModel {
ListElement { name: "Item 1" }
ListElement { name: "Item 2" }
ListElement { name: "Item 3" }
}
model: [ "Item 1", "Item 2", "Item 3" ]
model: 10 Используйте C++ для динамических наборов данных, которые большие или часто изменяются.
Взаимодействие с QML из C++
Хотя Qt позволяет изменять QML из C++, делать это не рекомендуется. Чтобы объяснить почему, давайте рассмотрим упрощенный пример.
Получение ссылок из QML
Предположим, мы пишем UI для страницы настроек:
import QtQuick 2.11
import QtQuick.Controls 2.4
Page {
Button {
text: qsTr("Restore default settings")
}
} Мы хотим, чтобы кнопка выполняла что-то в C++ при нажатии. Мы знаем, что объекты в QML могут генерировать сигналы изменения, как и в C++, поэтому мы даём кнопке objectName, чтобы мы могли найти её из C++:
Button {
objectName: "restoreDefaultsButton"
text: qsTr("Restore default settings")
} Затем в C++ мы находим этот объект и подключаемся к его сигналу изменения:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>
class Backend : public QObject
{
Q_OBJECT
public:
Backend() {}
public slots:
void restoreDefaults() {
settings.setValue("loadLastProject", QVariant(false));
}
private:
QSettings settings;
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
Backend backend;
QObject *rootObject = engine.rootObjects().first();
QObject *restoreDefaultsButton = rootObject->findChild<QObject*>("restoreDefaultsButton");
QObject::connect(restoreDefaultsButton, SIGNAL(clicked()),
&backend, SLOT(restoreDefaults()));
return app.exec();
}
#include "main.moc" С этим подходом ссылки на объекты «вытягиваются» из QML. Проблема в том, что слой логики C++ зависит от слоя представления QML. Если мы переработаем QML таким образом, что objectName изменится, или какое-либо другое изменение нарушит возможность для C++ найти объект QML, наш рабочий процесс становится намного более сложным и трудоёмким.
Направление ссылок в QML
Переработка QML намного проще, чем переработка C++, поэтому для того, чтобы минимизировать трудности поддержки, мы должны стремиться к тому, чтобы типы C++ были максимально независимыми от QML. Этого можно добиться, «направляя» ссылки на типы C++ в QML:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
Backend backend;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("backend", &backend);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
} Затем QML напрямую вызывает слот C++:
import QtQuick 2.11
import QtQuick.Controls 2.4
Page {
Button {
text: qsTr("Restore default settings")
onClicked: backend.restoreDefaults()
}
} С этим подходом C++ остаётся неизменным в случае необходимости дальнейшей переработки QML в будущем.
В примере выше мы устанавливаем контекстную переменную в корневом контексте, чтобы открыть объект C++ в QML. Это означает, что свойство доступно для каждого компонента, загруженного движком. Контекстные свойства полезны для объектов, которые должны быть доступны сразу после загрузки QML и не могут быть созданы в QML.
Для краткого руководства по выбору правильного подхода к экспонированию типов C++ в QML см. Выбор правильного метода интеграции между C++ и QML.
Связанная информация
Использование Qt Quick Layouts
Qt предлагает Qt Quick Layouts для визуального расположения элементов Qt Quick в макете. В отличие от альтернативного метода, позиционеров элементов, Qt Quick Layouts также могут изменять размер своих дочерних элементов при изменении размера окна. Хотя Qt Quick Layouts часто являются предпочтительным выбором для большинства случаев использования, при их использовании необходимо учитывать следующие «до» и «нельзя»:
Должно
- Используйте anchors или свойства width и height для указания размера макета относительно родительского элемента, который не является макетом.
- Используйте присоединённое свойство Layout для установки атрибутов размера и выравнивания дочерних элементов макета.
Не должно
- Не определяйте предпочтительные размеры для элементов, которые предоставляют implicitWidth и implicitHeight, если их неявные размеры не удовлетворяют требованиям.
- Не используйте anchors для элемента, который является непосредственным потомком макета. Вместо этого используйте
Layout.preferredWidthиLayout.preferredHeight:RowLayout { id: layout anchors.fill: parent spacing: 6 Rectangle { color: 'azure' Layout.fillWidth: true Layout.minimumWidth: 50 Layout.preferredWidth: 100 Layout.maximumWidth: 300 Layout.minimumHeight: 150 Text { anchors.centerIn: parent text: parent.width + 'x' + parent.height } } Rectangle { color: 'plum' Layout.fillWidth: true Layout.minimumWidth: 100 Layout.preferredWidth: 200 Layout.preferredHeight: 100 Text { anchors.centerIn: parent text: parent.width + 'x' + parent.height } } }
Примечание: Макеты и anchors — это типы объектов, которые занимают больше памяти и времени инициализации. Избегайте их использования (особенно в делегатах списков и таблиц, и стилях для элементов управления), если простые привязки к свойствам x, y, width и height достаточно.
Связанная информация
Безопасность типов
При объявлении свойств в QML легко и удобно использовать тип «var»:
property var name property var size property var optionsMenu
Однако этот подход имеет несколько недостатков:
- Если присваивается значение неправильного типа, ошибка будет указана в месте объявления свойства, а не в месте присвоения свойства. Это замедляет процесс разработки, затрудняя поиск ошибок.
- Статический анализ для обнаружения ошибок, упомянутых выше, невозможен.
- Фактический базовый тип свойства не всегда сразу понятен для читателя.
Вместо этого всегда используйте фактический тип, где это возможно:
property string name property int size property MyMenu optionsMenu
Производительность
Для получения информации о производительности в QML и Qt Quick см. Рекомендации по производительности и предложения.
Инструменты и утилиты
Для получения информации об полезных инструментах и утилитах, которые облегчают работу с QML и Qt Quick, см. Инструменты и утилиты Qt Quick.
Граф сцены
Для получения информации о графике сцены Qt Quick см. Граф сцены Qt Quick.
Масштабируемые пользовательские интерфейсы
По мере улучшения разрешений дисплеев масштабируемый пользовательский интерфейс приложения становится все более важным. Одним из подходов к этому является сохранение нескольких копий UI для разных разрешений экрана и загрузка соответствующей в зависимости от доступного разрешения. Хотя это работает довольно хорошо, это добавляет к нагрузке по обслуживанию.
Qt предлагает лучшее решение этой проблемы и рекомендует разработчикам приложений следовать этим советам:
- Используйте якоря или модуль Qt Quick Layouts для размещения визуальных элементов.
- Не указывайте явную ширину и высоту для визуального элемента.
- Предоставляйте ресурсы пользовательского интерфейса, такие как изображения и значки, для каждого разрешения экрана, поддерживаемого вашим приложением. Пример галереи Qt Quick Controls 2 демонстрирует это хорошо, предоставляя
qt-logo.pngдля@2x,@3x, и@4xразрешений, что позволяет приложению адаптироваться к дисплеям высокого разрешения. Qt автоматически выбирает подходящее изображение для данного дисплея, при условии, что функция масштабирования высокого DPI явно включена. - Используйте SVG-изображения для небольших значков. Хотя большие SVG могут медленно отображаться, маленькие работают хорошо. Векторные изображения позволяют избежать необходимости предоставлять несколько версий изображения, как это необходимо с растровыми изображениями.
- Используйте значки на основе шрифтов, такие как Font Awesome. Они масштабируются до любого разрешения экрана и также позволяют изменять цвет. Пример Qt Quick Controls 2 Text Editor демонстрирует это хорошо.
При выполнении этих условий пользовательский интерфейс вашего приложения должен масштабироваться в зависимости от разрешения отображения.
Справочная информация
- Пример галереи
- Пример текстового редактора
- Font Awesome
- Масштабируемость
- Дисплеи высокого разрешения
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/qtquick-bestpractices.html