Введение
Статья 484 показала, как создавать собственные компоненты «с нуля» через Rectangle/MouseArea — Qt Quick Controls предоставляет готовый набор стандартных элементов управления (кнопки, поля ввода, слайдеры, аналогичные элементам Qt Widgets) с встроенной поддержкой нескольких стилей оформления — в этой статье разберём систему стилизации и кастомизации этих готовых компонентов.
Концепция
Qt Quick Controls 2 предоставляет несколько встроенных стилей (Basic, Fusion, Material, Universal, imagine), задающих общий визуальный облик всех стандартных элементов управления приложения, выбираемых через настройку приложения (переменная окружения, аргумент командной строки, или явный import конкретного стиля) — переключение между стилями меняет внешний вид всех используемых стандартных элементов сразу, без необходимости менять сам QML-код, использующий эти элементы. Для более тонкой настройки внешнего вида конкретного элемента (в дополнение к выбранной общей теме или вместо неё) Qt Quick Controls 2 поддерживает кастомизацию через переопределение свойств background/contentItem конкретного экземпляра элемента (как было показано вскользь в статье 479 для Button), либо через создание полноценного, переопределяющего конкретный стиль файла для всего приложения.
Пример кода: Qt Quick Controls 2
// Выбор стиля через явный импорт в самом начале файла main.qml
import QtQuick
import QtQuick.Controls.Material // конкретный, явно выбранный стиль
ApplicationWindow {
visible: true
width: 400; height: 300
Material.theme: Material.Dark // дополнительная настройка конкретного стиля Material
Material.accent: Material.Teal
Column {
anchors.centerIn: parent
Button { text: "Кнопка в стиле Material Dark" }
Switch { text: "Переключатель" }
}
}
// Кастомизация конкретного экземпляра элемента через background/contentItem
import QtQuick
import QtQuick.Controls
Button {
text: "Кастомная кнопка"
background: Rectangle {
color: parent.pressed ? "#1565c0" : "#1976d2"
radius: 8
Behavior on color { ColorAnimation { duration: 150 } } // статья 487 — плавный переход цвета
}
contentItem: Text {
text: parent.text
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
; Выбор стиля без изменения кода — через переменную окружения (удобно для тестирования разных стилей)
; QT_QUICK_CONTROLS_STYLE=Fusion ./MyApp
Пояснения к коду
import QtQuick.Controls.Material явно выбирает конкретный стиль для всего приложения — все последующие стандартные элементы (Button, Switch) автоматически используют визуальный язык Material Design, и дополнительные свойства (Material.theme, Material.accent) дают специфичную для этого конкретного стиля тонкую настройку (тёмная/светлая тема, акцентный цвет), недоступную для других стилей в том же виде. Кастомизация через background/contentItem показывает точечный, локальный подход — переопределение внешнего вида конкретного экземпляра Button без изменения общего, глобального стиля остальных элементов приложения, что полезно для отдельных, особо важных или нестандартных по дизайну элементов интерфейса. Переменная окружения QT_QUICK_CONTROLS_STYLE показывает альтернативный, не требующий изменения кода способ выбора стиля — особенно удобный для быстрого визуального сравнения разных стилей без необходимости пересборки или редактирования исходного кода приложения.
Подводные камни
- Смешивание элементов, явно кастомизированных через
background/contentItem, с элементами, использующими стиль по умолчанию, без продуманной, согласованной визуальной системы — частичная, несистемная кастомизация отдельных элементов на фоне остальных, не кастомизированных элементов того же приложения может создать визуально несогласованный, «разнородный» интерфейс, и для масштабной кастомизации внешнего вида стоит рассмотреть создание полноценного, согласованного пользовательского стиля для всего приложения, а не точечные, разрозненные переопределения отдельных экземпляров. - Жёсткая привязка кода приложения к конкретному выбранному стилю, использующая специфичные для этого стиля свойства (
Material.theme) в коде, который теоретически должен оставаться независимым от конкретного выбора стиля — если приложение должно поддерживать переключение между разными стилями (а не быть жёстко привязанным к одному, заранее выбранному), специфичные для конкретного стиля настройки (какMaterial.theme) нужно использовать осторожно, с пониманием, что они применимы только при реально выбранном соответствующем стиле. - Игнорирование платформенных соглашений об интерфейсе при выборе стиля для desktop-приложения, использующего стиль, ориентированный преимущественно на мобильные платформы (Material Design исторически ассоциируется с Android) для desktop-приложения, предназначенного для пользователей, ожидающих более привычный, нативный для конкретной desktop-платформы внешний вид — выбор стиля должен учитывать реальную целевую платформу и ожидания её типичных пользователей, а не выбираться произвольно без учёта контекста использования приложения.
- Недостаточное тестирование кастомизированных компонентов на разных размерах экрана/разрешениях — кастомный
background/contentItem, визуально корректный при тестировании на одном конкретном размере окна, может не вести себя ожидаемым образом при ином размере или соотношении сторон (статья 497, адаптивный UI), особенно если кастомизация использует фиксированные, не адаптирующиеся к изменению размера значения вместо относительных, привязанных к размеру родителя величин.