Настройка Qt Quick Controls 2
Qt Quick Controls 2 состоят из иерархии (дерева) элементов. Для предоставления пользовательского вида и ощущения, реализация каждого элемента по умолчанию в QML может быть заменена пользовательской.
Настройка элемента управления
Иногда вам нужно создать уникальный вид для определённой части вашего пользовательского интерфейса и использовать стандартную стилизацию для всех остальных элементов. Возможно, вам нравится используемая стилизация, но есть определённая кнопка, имеющая особое значение.
Первый способ создания такой кнопки — определить её непосредственно там, где она требуется. Например, предположим, что вас не устраивает квадратный вид углов кнопки по умолчанию. Чтобы сделать их закруглёнными, вы можете переопределить элемент background и установить свойство radius прямоугольника:
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
width: 400
height: 400
visible: true
Button {
id: button
text: "A Special Button"
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
color: button.down ? "#d6d6d6" : "#f6f6f6"
border.color: "#26282a"
border.width: 1
radius: 4
}
}
} Второй способ создания кнопки полезен, если вы планируете использовать закруглённую кнопку в нескольких местах. Он подразумевает перемещение кода в отдельный файл QML в вашем проекте.
Для этого подхода мы скопируем код фона из стандартной стилизации Button.qml. Этот файл можно найти по следующему пути в вашей установке Qt:
$QTDIR/qml/QtQuick/Controls.2/Button.qml
После этого просто добавим следующую строку:
radius: 4
Чтобы избежать путаницы с элементами управления в самом модуле, мы назовём этот файл MyButton.qml. Для использования элемента управления в вашем приложении, ссылайтесь на него по имени файла:
import QtQuick.Controls 2.13
ApplicationWindow {
MyButton {
text: qsTr("A Special Button")
}
} Третий способ создания кнопки более структурирован как с точки зрения расположения файла в файловой системе, так и с точки зрения его использования в QML. Сначала скопируйте существующий файл, как и в предыдущем способе, но на этот раз поместите его в подпапку вашего проекта, например, controls. Чтобы использовать элемент управления, сначала импортируйте папку в пространство имён:
import QtQuick.Controls 2.13
import "controls" as MyControls
ApplicationWindow {
MyControls.Button {
text: qsTr("A Special Button")
}
} Теперь у вас есть пространство имён MyControls, и вы можете именовать элементы управления так же, как и их аналоги в модуле Qt Quick Controls 2. Вы можете повторить этот процесс для любого элемента управления, который хотите добавить.
Дополнительное преимущество этих трёх методов заключается в том, что не нужно реализовывать шаблон с нуля.
Создание пользовательской стилизации
Существует несколько способов создания собственных стилизаций. Ниже мы объясним различные подходы.
Определение стилизации
В Qt Quick Controls 2 стилизация — это по существу набор взаимозаменяемых файлов QML в одной директории. Для того, чтобы стилизация была использована, требуется три условия:
- Должен существовать хотя бы один файл QML, имя которого соответствует элементу управления (например,
Button.qml) - Каждый файл QML должен содержать соответствующий тип из импорта QtQuick.Templates в качестве корневого элемента. Например, Button.qml должен содержать шаблон Button в качестве корневого элемента.
Если вместо этого мы использовали бы соответствующий тип из импорта QtQuick.Controls, как мы делали в предыдущем разделе, это не сработает: элемент управления, который мы определяем, попытается унаследовать от себя самого.
- Файлы должны находиться в директории в файловой системе или в системе ресурсов.
Например, вот все допустимые пути к стилизации:
./myapp -style /home/absolute/path/to/my/style./myapp -style :/mystyle./myapp -style relative/path/to/my/style./myapp -style MyStyle
Третий и четвёртый пути будут проверяться в списке путей импорта движка QML. Это то же, что происходит, когда вы передаёте
Materialв качестве стилизации, например.
По умолчанию система стилизации использует стилизация по умолчанию в качестве резервного варианта для элементов управления, которые не реализованы. Для настройки или расширения любой другой встроенной стилизации можно указать другую стилизации по умолчанию с помощью QQuickStyle.
Это означает, что вы можете реализовывать любые элементы управления, которые вам нужны, для вашей пользовательской стилизации и размещать их практически где угодно. Это также позволяет пользователям создавать свои собственные стили для вашего приложения.
Предварительный просмотр пользовательских стилизаций в Qt Quick Designer
Используя описанный выше подход, можно предварительно просмотреть пользовательскую стилизацию в Qt Quick Designer. Для этого убедитесь, что в проекте есть файл qtquickcontrols2.conf и что существует следующая запись:
[Controls] Style=MyStyle
Дополнительную информацию можно найти в примере Flat Style.
Расширения стилизации на C++
Иногда вам может понадобиться использовать C++, чтобы расширить вашу пользовательскую стилизацию. Существует два способа экспонировать такие типы в QML:
- Если стиль, использующий тип, является единственным используемым стилем в приложении, достаточно зарегистрировать его в движке QML с помощью qmlRegisterType():
qmlRegisterType<ACoolCppItem>("MyApp", 1, 0, "ACoolItem");Дополнительную информацию см. в разделе Использование данных C++ из QML.
- Если стиль, использующий тип, — один из многих стилей, используемых приложением, может быть лучше зарегистрировать его только при необходимости. В этом случае имеет смысл реализовать собственный QML плагин.
Использование плагина как части вашей стилизации не сильно отличается от использования набора файлов QML. Единственное отличие заключается в том, что плагин и его
qmldirфайл должны находиться в той же директории, что и файлы QML.
Присоединенные свойства
Для стилизации часто характерно наличие определённых свойств или атрибутов, которые применяются ко всем элементам управления. Присоединённые свойства — отличный способ расширения элемента в QML без изменения существующего C++ этого элемента. Например, в стилях Material и Universal есть присоединённое свойство theme, которое управляет тем, будут ли элемент и его дочерние элементы отрисовываться в светлой или тёмной теме.
В качестве примера добавим присоединённое свойство, которое управляет подъёмом. Наша стилизация продемонстрирует подъём с помощью тени; чем выше подъём, тем больше тень.
Первый шаг — создание нового приложения Qt Quick Controls 2 в Qt Creator. После этого мы добавляем тип C++, который хранит подъём. Поскольку этот тип будет использоваться для каждого элемента управления, поддерживаемого нашей стилизацией, и поскольку мы можем захотеть добавить другие присоединённые свойства позже, мы назовём его MyStyle. Вот MyStyle.h:
#ifndef MYSTYLE_H
#define MYSTYLE_H
#include <QObject>
#include <QtQml>
class MyStyle : public QObject
{
Q_OBJECT
Q_PROPERTY(int elevation READ elevation WRITE setElevation NOTIFY elevationChanged)
public:
explicit MyStyle(QObject *parent = nullptr);
static MyStyle *qmlAttachedProperties(QObject *object);
int elevation() const;
void setElevation(int elevation);
signals:
void elevationChanged();
private:
int m_elevation;
};
QML_DECLARE_TYPEINFO(MyStyle, QML_HAS_ATTACHED_PROPERTIES)
#endif // MYSTYLE_H MyStyle.cpp:
#include "mystyle.h"
MyStyle::MyStyle(QObject *parent) :
QObject(parent),
m_elevation(0)
{
}
MyStyle *MyStyle::qmlAttachedProperties(QObject *object)
{
return new MyStyle(object);
}
int MyStyle::elevation() const
{
return m_elevation;
}
void MyStyle::setElevation(int elevation)
{
if (elevation == m_elevation)
return;
m_elevation = elevation;
emit elevationChanged();
} Тип MyStyle является специальным в том смысле, что его нельзя создавать, а вместо этого использовать для присоединённых свойств. Поэтому мы регистрируем его следующим образом в main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "mystyle.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterUncreatableType<MyStyle>("MyStyle", 1, 0, "MyStyle", "MyStyle is an attached property");
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
} Затем мы копируем Button.qml из стилизации по умолчанию в $QTDIR/qml/QtQuick/Controls.2/ в новую папку myproject в нашей папке проекта. Добавьте скопированный Button.qml в qml.qrc, который является файлом ресурсов, содержащим наши файлы QML.
Далее, мы добавляем тень к делегату фона background кнопки:
// ...
import QtGraphicalEffects 1.13
import MyStyle 1.0
// ...
background: Rectangle {
// ...
layer.enabled: control.enabled && control.MyStyle.elevation > 0
layer.effect: DropShadow {
verticalOffset: 1
color: control.visualFocus ? "#330066ff" : "#aaaaaa"
samples: control.MyStyle.elevation
spread: 0.5
}
} Обратите внимание, что мы:
- Не используем тень, когда подъём равен
0 - Изменяем цвет тени в зависимости от того, фокусирована ли кнопка
- Делаем размер тени зависящим от подъёма
Чтобы опробовать присоединённое свойство, создадим Row с двумя кнопками в main.qml:
import QtQuick 2.13
import QtQuick.Controls 2.13
import MyStyle 1.0
ApplicationWindow {
id: window
width: 400
height: 400
visible: true
Row {
spacing: 20
anchors.centerIn: parent
Button {
text: "Button 1"
}
Button {
text: "Button 2"
MyStyle.elevation: 10
}
}
} Одна кнопка не имеет подъёма, а другая имеет подъём 10.
После этого мы можем запустить наш пример. Чтобы указать приложению использовать нашу новую стилизацию, мы передаём -style :/mystyle в качестве аргумента приложения, но есть много способов указать используемую стилизацию.
Конечный результат:
Обратите внимание, что оператор import MyStyle 1.0 необходим только потому, что мы используем присоединённое свойство, принадлежащее MyStyle. Обе кнопки будут использовать нашу пользовательскую стилизацию, даже если мы удалим импорт.
Справочник по настройке
В следующих фрагментах приведены примеры, в которых элементы управления по умолчанию были настроенны с использованием того же подхода, что и в разделе Настройка элемента управления. Код можно использовать в качестве отправной точки для реализации пользовательского вида и ощущения.
Настройка ApplicationWindow
ApplicationWindow состоит из одного визуального элемента: background. Также можно настроить элементы modal и modeless.
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
visible: true
background: Rectangle {
gradient: Gradient {
GradientStop { position: 0; color: "#ffffff" }
GradientStop { position: 1; color: "#c1bbf9" }
}
}
overlay.modal: Rectangle {
color: "#8f28282a"
}
overlay.modeless: Rectangle {
color: "#2f28282a"
}
} Настройка BusyIndicator
BusyIndicator состоит из двух визуальных элементов: background и contentItem.
import QtQuick 2.12
import QtQuick.Controls 2.12
BusyIndicator {
id: control
contentItem: Item {
implicitWidth: 64
implicitHeight: 64
Item {
id: item
x: parent.width / 2 - 32
y: parent.height / 2 - 32
width: 64
height: 64
opacity: control.running ? 1 : 0
Behavior on opacity {
OpacityAnimator {
duration: 250
}
}
RotationAnimator {
target: item
running: control.visible && control.running
from: 0
to: 360
loops: Animation.Infinite
duration: 1250
}
Repeater {
id: repeater
model: 6
Rectangle {
x: item.width / 2 - width / 2
y: item.height / 2 - height / 2
implicitWidth: 10
implicitHeight: 10
radius: 5
color: "#21be2b"
transform: [
Translate {
y: -Math.min(item.width, item.height) * 0.5 + 5
},
Rotation {
angle: index / repeater.count * 360
origin.x: 5
origin.y: 5
}
]
}
}
}
}
} Настройка Button
Button состоит из двух визуальных элементов: background и content item.
import QtQuick 2.12
import QtQuick.Controls 2.12
Button {
id: control
text: qsTr("Button")
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
opacity: enabled ? 1 : 0.3
border.color: control.down ? "#17a81a" : "#21be2b"
border.width: 1
radius: 2
}
} Настройка CheckBox
CheckBox состоит из трёх визуальных элементов: background, contentItem и indicator.
import QtQuick 2.12
import QtQuick.Controls 2.12
CheckBox {
id: control
text: qsTr("CheckBox")
checked: true
indicator: Rectangle {
implicitWidth: 26
implicitHeight: 26
x: control.leftPadding
y: parent.height / 2 - height / 2
radius: 3
border.color: control.down ? "#17a81a" : "#21be2b"
Rectangle {
width: 14
height: 14
x: 6
y: 6
radius: 2
color: control.down ? "#17a81a" : "#21be2b"
visible: control.checked
}
}
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: control.indicator.width + control.spacing
}
} Настройка CheckDelegate
CheckDelegate состоит из трёх визуальных элементов: background, contentItem и indicator.
import QtQuick 2.12
import QtQuick.Controls 2.12
CheckDelegate {
id: control
text: qsTr("CheckDelegate")
checked: true
contentItem: Text {
rightPadding: control.indicator.width + control.spacing
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
indicator: Rectangle {
implicitWidth: 26
implicitHeight: 26
x: control.width - width - control.rightPadding
y: control.topPadding + control.availableHeight / 2 - height / 2
radius: 3
color: "transparent"
border.color: control.down ? "#17a81a" : "#21be2b"
Rectangle {
width: 14
height: 14
x: 6
y: 6
radius: 2
color: control.down ? "#17a81a" : "#21be2b"
visible: control.checked
}
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
visible: control.down || control.highlighted
color: control.down ? "#bdbebf" : "#eeeeee"
}
} Настройка ComboBox
Комбобокс состоит из фона, элемента содержимого, выпадающего списка, индикатора и делегата.
import QtQuick 2.12
import QtQuick.Controls 2.12
ComboBox {
id: control
model: ["First", "Second", "Third"]
delegate: ItemDelegate {
width: control.width
contentItem: Text {
text: modelData
color: "#21be2b"
font: control.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: control.highlightedIndex === index
}
indicator: Canvas {
id: canvas
x: control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
Connections {
target: control
onPressedChanged: canvas.requestPaint()
}
onPaint: {
context.reset();
context.moveTo(0, 0);
context.lineTo(width, 0);
context.lineTo(width / 2, height);
context.closePath();
context.fillStyle = control.pressed ? "#17a81a" : "#21be2b";
context.fill();
}
}
contentItem: Text {
leftPadding: 0
rightPadding: control.indicator.width + control.spacing
text: control.displayText
font: control.font
color: control.pressed ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
border.color: control.pressed ? "#17a81a" : "#21be2b"
border.width: control.visualFocus ? 2 : 1
radius: 2
}
popup: Popup {
y: control.height - 1
width: control.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
border.color: "#21be2b"
radius: 2
}
}
} Настройка DelayButton
Кнопка с задержкой состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
DelayButton {
id: control
checked: true
text: qsTr("Delay\nButton")
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 100
opacity: enabled ? 1 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
radius: size / 2
readonly property real size: Math.min(control.width, control.height)
width: size
height: size
anchors.centerIn: parent
Canvas {
id: canvas
anchors.fill: parent
Connections {
target: control
onProgressChanged: canvas.requestPaint()
}
onPaint: {
var ctx = getContext("2d")
ctx.clearRect(0, 0, width, height)
ctx.strokeStyle = "white"
ctx.lineWidth = parent.size / 20
ctx.beginPath()
var startAngle = Math.PI / 5 * 3
var endAngle = startAngle + control.progress * Math.PI / 5 * 9
ctx.arc(width / 2, height / 2, width / 2 - ctx.lineWidth / 2 - 2, startAngle, endAngle)
ctx.stroke()
}
}
}
} Настройка Поворотного регулятора
Поворотный регулятор состоит из двух визуальных элементов: фона и ручки.
import QtQuick 2.12
import QtQuick.Controls 2.12
Dial {
id: control
background: Rectangle {
x: control.width / 2 - width / 2
y: control.height / 2 - height / 2
width: Math.max(64, Math.min(control.width, control.height))
height: width
color: "transparent"
radius: width / 2
border.color: control.pressed ? "#17a81a" : "#21be2b"
opacity: control.enabled ? 1 : 0.3
}
handle: Rectangle {
id: handleItem
x: control.background.x + control.background.width / 2 - width / 2
y: control.background.y + control.background.height / 2 - height / 2
width: 16
height: 16
color: control.pressed ? "#17a81a" : "#21be2b"
radius: 8
antialiasing: true
opacity: control.enabled ? 1 : 0.3
transform: [
Translate {
y: -Math.min(control.background.width, control.background.height) * 0.4 + handleItem.height / 2
},
Rotation {
angle: control.angle
origin.x: handleItem.width / 2
origin.y: handleItem.height / 2
}
]
}
} Настройка Шкафа
Шкаф может иметь визуальный элемент фона.
background: Rectangle {
Rectangle {
x: parent.width - 1
width: 1
height: parent.height
color: "#21be2b"
}
} Настройка Рамки
Рамка состоит из одного визуального элемента: фона.
import QtQuick 2.12
import QtQuick.Controls 2.12
Frame {
background: Rectangle {
color: "transparent"
border.color: "#21be2b"
radius: 2
}
Label {
text: qsTr("Content goes here!")
}
} Настройка GroupBox
Группа состоит из двух визуальных элементов: фона и метки.
import QtQuick 2.12
import QtQuick.Controls 2.12
GroupBox {
id: control
title: qsTr("GroupBox")
background: Rectangle {
y: control.topPadding - control.bottomPadding
width: parent.width
height: parent.height - control.topPadding + control.bottomPadding
color: "transparent"
border.color: "#21be2b"
radius: 2
}
label: Label {
x: control.leftPadding
width: control.availableWidth
text: control.title
color: "#21be2b"
elide: Text.ElideRight
}
Label {
text: qsTr("Content goes here!")
}
} Настройка ItemDelegate
Делегат элемента состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ItemDelegate {
id: control
text: qsTr("ItemDelegate")
contentItem: Text {
rightPadding: control.spacing
text: control.text
font: control.font
color: control.enabled ? (control.down ? "#17a81a" : "#21be2b") : "#bdbebf"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
opacity: enabled ? 1 : 0.3
color: control.down ? "#dddedf" : "#eeeeee"
Rectangle {
width: parent.width
height: 1
color: control.down ? "#17a81a" : "#21be2b"
anchors.bottom: parent.bottom
}
}
} Настройка Метки
Метка может иметь визуальный элемент фона.
import QtQuick 2.12
import QtQuick.Controls 2.12
Label {
text: qsTr("Label")
color: "#21be2b"
} Настройка Меню
- Меню состоит из визуального элемента фона.
- Элемент меню состоит из четырёх визуальных элементов: фона, элемента содержимого, индикатора и стрелки.
- Разделитель меню состоит из визуального фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
Menu {
id: menu
Action { text: qsTr("Tool Bar"); checkable: true }
Action { text: qsTr("Side Bar"); checkable: true; checked: true }
Action { text: qsTr("Status Bar"); checkable: true; checked: true }
MenuSeparator {
contentItem: Rectangle {
implicitWidth: 200
implicitHeight: 1
color: "#21be2b"
}
}
Menu {
title: qsTr("Advanced")
// ...
}
topPadding: 2
bottomPadding: 2
delegate: MenuItem {
id: menuItem
implicitWidth: 200
implicitHeight: 40
arrow: Canvas {
x: parent.width - width
implicitWidth: 40
implicitHeight: 40
visible: menuItem.subMenu
onPaint: {
var ctx = getContext("2d")
ctx.fillStyle = menuItem.highlighted ? "#ffffff" : "#21be2b"
ctx.moveTo(15, 15)
ctx.lineTo(width - 15, height / 2)
ctx.lineTo(15, height - 15)
ctx.closePath()
ctx.fill()
}
}
indicator: Item {
implicitWidth: 40
implicitHeight: 40
Rectangle {
width: 26
height: 26
anchors.centerIn: parent
visible: menuItem.checkable
border.color: "#21be2b"
radius: 3
Rectangle {
width: 14
height: 14
anchors.centerIn: parent
visible: menuItem.checked
color: "#21be2b"
radius: 2
}
}
}
contentItem: Text {
leftPadding: menuItem.indicator.width
rightPadding: menuItem.arrow.width
text: menuItem.text
font: menuItem.font
opacity: enabled ? 1.0 : 0.3
color: menuItem.highlighted ? "#ffffff" : "#21be2b"
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 200
implicitHeight: 40
opacity: enabled ? 1 : 0.3
color: menuItem.highlighted ? "#21be2b" : "transparent"
}
}
background: Rectangle {
implicitWidth: 200
implicitHeight: 40
color: "#ffffff"
border.color: "#21be2b"
radius: 2
}
} Настройка Панели меню
Панель меню может иметь визуальный элемент фона, а Элемент панели меню состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
MenuBar {
id: menuBar
Menu { title: qsTr("File") }
Menu { title: qsTr("Edit") }
Menu { title: qsTr("View") }
Menu { title: qsTr("Help") }
delegate: MenuBarItem {
id: menuBarItem
contentItem: Text {
text: menuBarItem.text
font: menuBarItem.font
opacity: enabled ? 1.0 : 0.3
color: menuBarItem.highlighted ? "#ffffff" : "#21be2b"
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 40
implicitHeight: 40
opacity: enabled ? 1 : 0.3
color: menuBarItem.highlighted ? "#21be2b" : "transparent"
}
}
background: Rectangle {
implicitWidth: 40
implicitHeight: 40
color: "#ffffff"
Rectangle {
color: "#21be2b"
width: parent.width
height: 1
anchors.bottom: parent.bottom
}
}
} Настройка Индикатора страниц
Индикатор страниц состоит из фона, элемента содержимого и делегата.
import QtQuick 2.12
import QtQuick.Controls 2.12
PageIndicator {
id: control
count: 5
currentIndex: 2
delegate: Rectangle {
implicitWidth: 8
implicitHeight: 8
radius: width / 2
color: "#21be2b"
opacity: index === control.currentIndex ? 0.95 : pressed ? 0.7 : 0.45
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
} Настройка Панели
Панель состоит из фона.
import QtQuick 2.12
import QtQuick.Controls 2.12
Pane {
background: Rectangle {
color: "#eeeeee"
}
Label {
text: qsTr("Content goes here!")
}
} Настройка Выпадающего списка
Выпадающий список состоит из фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
Popup {
id: popup
background: Rectangle {
implicitWidth: 200
implicitHeight: 200
border.color: "#444"
}
contentItem: Column {}
} Настройка Полосы прогресса
Полоса прогресса состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ProgressBar {
id: control
value: 0.5
padding: 2
background: Rectangle {
implicitWidth: 200
implicitHeight: 6
color: "#e6e6e6"
radius: 3
}
contentItem: Item {
implicitWidth: 200
implicitHeight: 4
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
radius: 2
color: "#17a81a"
}
}
} Настройка Радиокнопки
Радиокнопка состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.
import QtQuick 2.12
import QtQuick.Controls 2.12
RadioButton {
id: control
text: qsTr("RadioButton")
checked: true
indicator: Rectangle {
implicitWidth: 26
implicitHeight: 26
x: control.leftPadding
y: parent.height / 2 - height / 2
radius: 13
border.color: control.down ? "#17a81a" : "#21be2b"
Rectangle {
width: 14
height: 14
x: 6
y: 6
radius: 7
color: control.down ? "#17a81a" : "#21be2b"
visible: control.checked
}
}
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: control.indicator.width + control.spacing
}
} Настройка Делегата Радиокнопки
Делегат радиокнопки состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.
import QtQuick 2.12
import QtQuick.Controls 2.12
RadioDelegate {
id: control
text: qsTr("RadioDelegate")
checked: true
contentItem: Text {
rightPadding: control.indicator.width + control.spacing
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
indicator: Rectangle {
implicitWidth: 26
implicitHeight: 26
x: control.width - width - control.rightPadding
y: parent.height / 2 - height / 2
radius: 13
color: "transparent"
border.color: control.down ? "#17a81a" : "#21be2b"
Rectangle {
width: 14
height: 14
x: 6
y: 6
radius: 7
color: control.down ? "#17a81a" : "#21be2b"
visible: control.checked
}
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
visible: control.down || control.highlighted
color: control.down ? "#bdbebf" : "#eeeeee"
}
} Настройка Диапазонного ползунка
Диапазонный ползунок состоит из трёх визуальных элементов: фона, первой ручки и второй ручки.
import QtQuick 2.12
import QtQuick.Controls 2.12
RangeSlider {
id: control
first.value: 0.25
second.value: 0.75
background: Rectangle {
x: control.leftPadding
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: control.availableWidth
height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
x: control.first.visualPosition * parent.width
width: control.second.visualPosition * parent.width - x
height: parent.height
color: "#21be2b"
radius: 2
}
}
first.handle: Rectangle {
x: control.leftPadding + first.visualPosition * (control.availableWidth - width)
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: first.pressed ? "#f0f0f0" : "#f6f6f6"
border.color: "#bdbebf"
}
second.handle: Rectangle {
x: control.leftPadding + second.visualPosition * (control.availableWidth - width)
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: second.pressed ? "#f0f0f0" : "#f6f6f6"
border.color: "#bdbebf"
}
} Настройка Круглого элемента
Круглая кнопка может быть настроена так же, как и Кнопка.
Настройка полосы прокрутки
Полоса прокрутки состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ScrollBar {
id: control
size: 0.3
position: 0.2
active: true
orientation: Qt.Vertical
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: control.pressed ? "#81e889" : "#c2f4c6"
}
} Настройка индикатора прокрутки
Индикатор прокрутки состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ScrollIndicator {
id: control
size: 0.3
position: 0.2
active: true
orientation: Qt.Vertical
contentItem: Rectangle {
implicitWidth: 2
implicitHeight: 100
color: "#c2f4c6"
}
} Настройка области прокрутки
Область прокрутки состоит из элемента фона, а также горизонтальной и вертикальной полос прокрутки.
ScrollView {
id: control
width: 200
height: 200
focus: true
Label {
text: "ABC"
font.pixelSize: 224
}
ScrollBar.vertical: ScrollBar {
parent: control
x: control.mirrored ? 0 : control.width - width
y: control.topPadding
height: control.availableHeight
active: control.ScrollBar.horizontal.active
}
ScrollBar.horizontal: ScrollBar {
parent: control
x: control.leftPadding
y: control.height - height
width: control.availableWidth
active: control.ScrollBar.vertical.active
}
background: Rectangle {
border.color: control.activeFocus ? "#21be2b" : "#bdbebf"
}
} Настройка ползунка
Ползунок состоит из двух визуальных элементов: фона и ручки.
import QtQuick 2.12
import QtQuick.Controls 2.12
Slider {
id: control
value: 0.5
background: Rectangle {
x: control.leftPadding
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: control.availableWidth
height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
color: "#21be2b"
radius: 2
}
}
handle: Rectangle {
x: control.leftPadding + control.visualPosition * (control.availableWidth - width)
y: control.topPadding + control.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: control.pressed ? "#f0f0f0" : "#f6f6f6"
border.color: "#bdbebf"
}
} Настройка SpinBox
SpinBox состоит из четырёх визуальных элементов: фона, contentItem, индикатора вверх и индикатора вниз.
import QtQuick 2.12
import QtQuick.Controls 2.12
SpinBox {
id: control
value: 50
editable: true
contentItem: TextInput {
z: 2
text: control.textFromValue(control.value, control.locale)
font: control.font
color: "#21be2b"
selectionColor: "#21be2b"
selectedTextColor: "#ffffff"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
readOnly: !control.editable
validator: control.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
x: control.mirrored ? 0 : parent.width - width
height: parent.height
implicitWidth: 40
implicitHeight: 40
color: control.up.pressed ? "#e4e4e4" : "#f6f6f6"
border.color: enabled ? "#21be2b" : "#bdbebf"
Text {
text: "+"
font.pixelSize: control.font.pixelSize * 2
color: "#21be2b"
anchors.fill: parent
fontSizeMode: Text.Fit
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
down.indicator: Rectangle {
x: control.mirrored ? parent.width - width : 0
height: parent.height
implicitWidth: 40
implicitHeight: 40
color: control.down.pressed ? "#e4e4e4" : "#f6f6f6"
border.color: enabled ? "#21be2b" : "#bdbebf"
Text {
text: "-"
font.pixelSize: control.font.pixelSize * 2
color: "#21be2b"
anchors.fill: parent
fontSizeMode: Text.Fit
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
background: Rectangle {
implicitWidth: 140
border.color: "#bdbebf"
}
} Настройка SplitView
SplitView состоит из визуального делегата ручки.
SplitView {
id: splitView
anchors.fill: parent
handle: Rectangle {
implicitWidth: 4
implicitHeight: 4
color: SplitHandle.pressed ? "#81e889"
: (SplitHandle.hovered ? Qt.lighter("#c2f4c6", 1.1) : "#c2f4c6")
}
Rectangle {
implicitWidth: 150
color: "#444"
}
Rectangle {
implicitWidth: 50
color: "#666"
}
} Настройка StackView
StackView может иметь визуальный элемент фона, и позволяет настраивать переходы, используемые для операций push, pop и replace.
import QtQuick 2.12
import QtQuick.Controls 2.12
StackView {
id: control
popEnter: Transition {
XAnimator {
from: (control.mirrored ? -1 : 1) * -control.width
to: 0
duration: 400
easing.type: Easing.OutCubic
}
}
popExit: Transition {
XAnimator {
from: 0
to: (control.mirrored ? -1 : 1) * control.width
duration: 400
easing.type: Easing.OutCubic
}
}
} Настройка SwipeDelegate
Делегат свайпа состоит из шести визуальных элементов: фона, элемента содержимого, индикатора, swipe.left, swipe.right, и swipe.behind.
import QtQuick 2.12
import QtQuick.Controls 2.12
SwipeDelegate {
id: control
text: qsTr("SwipeDelegate")
Component {
id: component
Rectangle {
color: SwipeDelegate.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
Label {
text: qsTr("Press me!")
color: "#21be2b"
anchors.centerIn: parent
}
}
}
swipe.left: component
swipe.right: component
contentItem: Text {
text: control.text
font: control.font
color: control.enabled ? (control.down ? "#17a81a" : "#21be2b") : "#bdbebf"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
Behavior on x {
enabled: !control.down
NumberAnimation {
easing.type: Easing.InOutCubic
duration: 400
}
}
}
} Настройка SwipeView
SwipeView может иметь визуальный элемент фона. Навигация реализуется с помощью элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
SwipeView {
id: control
background: Rectangle {
color: "#eeeeee"
}
} Настройка Переключателя
Переключатель состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.
import QtQuick 2.12
import QtQuick.Controls 2.12
Switch {
id: control
text: qsTr("Switch")
indicator: Rectangle {
implicitWidth: 48
implicitHeight: 26
x: control.leftPadding
y: parent.height / 2 - height / 2
radius: 13
color: control.checked ? "#17a81a" : "#ffffff"
border.color: control.checked ? "#17a81a" : "#cccccc"
Rectangle {
x: control.checked ? parent.width - width : 0
width: 26
height: 26
radius: 13
color: control.down ? "#cccccc" : "#ffffff"
border.color: control.checked ? (control.down ? "#17a81a" : "#21be2b") : "#999999"
}
}
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: control.indicator.width + control.spacing
}
} Настройка делегата переключателя
Делегат переключателя состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.
import QtQuick 2.12
import QtQuick.Controls 2.12
SwitchDelegate {
id: control
text: qsTr("SwitchDelegate")
checked: true
contentItem: Text {
rightPadding: control.indicator.width + control.spacing
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
indicator: Rectangle {
implicitWidth: 48
implicitHeight: 26
x: control.width - width - control.rightPadding
y: parent.height / 2 - height / 2
radius: 13
color: control.checked ? "#17a81a" : "transparent"
border.color: control.checked ? "#17a81a" : "#cccccc"
Rectangle {
x: control.checked ? parent.width - width : 0
width: 26
height: 26
radius: 13
color: control.down ? "#cccccc" : "#ffffff"
border.color: control.checked ? (control.down ? "#17a81a" : "#21be2b") : "#999999"
}
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
visible: control.down || control.highlighted
color: control.down ? "#bdbebf" : "#eeeeee"
}
} Настройка TabBar
TabBar состоит из двух визуальных элементов: фона и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
TabBar {
id: control
background: Rectangle {
color: "#eeeeee"
}
TabButton {
text: qsTr("Home")
}
TabButton {
text: qsTr("Discover")
}
TabButton {
text: qsTr("Activity")
}
} Настройка TabButton
Кнопка вкладки можно настроить аналогично кнопке.
Настройка TextArea
TextArea состоит из элемента фонового изображения.
import QtQuick 2.12
import QtQuick.Controls 2.12
TextArea {
id: control
placeholderText: qsTr("Enter description")
background: Rectangle {
implicitWidth: 200
implicitHeight: 40
border.color: control.enabled ? "#21be2b" : "transparent"
}
} Настройка TextField
TextField состоит из элемента фонового изображения.
import QtQuick 2.12
import QtQuick.Controls 2.12
TextField {
id: control
placeholderText: qsTr("Enter description")
background: Rectangle {
implicitWidth: 200
implicitHeight: 40
color: control.enabled ? "transparent" : "#353637"
border.color: control.enabled ? "#21be2b" : "transparent"
}
} Настройка ToolBar
ToolBar состоит из одного визуального элемента: фонового изображения.
ToolBar {
id: control
background: Rectangle {
implicitHeight: 40
color: "#eeeeee"
Rectangle {
width: parent.width
height: 1
anchors.bottom: parent.bottom
color: "transparent"
border.color: "#21be2b"
}
}
RowLayout {
anchors.fill: parent
ToolButton {
text: qsTr("Undo")
}
ToolButton {
text: qsTr("Redo")
}
}
} Настройка ToolButton
ToolButton состоит из двух визуальных элементов: фонового изображения и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ToolButton {
id: control
text: qsTr("ToolButton")
width: 120
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 40
implicitHeight: 40
color: Qt.darker("#33333333", control.enabled && (control.checked || control.highlighted) ? 1.5 : 1.0)
opacity: enabled ? 1 : 0.3
visible: control.down || (control.enabled && (control.checked || control.highlighted))
}
} Настройка ToolSeparator
ToolSeparator состоит из двух визуальных элементов: фонового изображения и элемента содержимого.
ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
text: qsTr("Action 1")
}
ToolButton {
text: qsTr("Action 2")
}
ToolSeparator {
padding: vertical ? 10 : 2
topPadding: vertical ? 2 : 10
bottomPadding: vertical ? 2 : 10
contentItem: Rectangle {
implicitWidth: parent.vertical ? 1 : 24
implicitHeight: parent.vertical ? 24 : 1
color: "#c3c3c3"
}
}
ToolButton {
text: qsTr("Action 3")
}
ToolButton {
text: qsTr("Action 4")
}
Item {
Layout.fillWidth: true
}
}
} Настройка ToolTip
ToolTip состоит из двух визуальных элементов: фонового изображения и элемента содержимого.
import QtQuick 2.12
import QtQuick.Controls 2.12
ToolTip {
id: control
text: qsTr("A descriptive tool tip of what the button does")
contentItem: Text {
text: control.text
font: control.font
color: "#21be2b"
}
background: Rectangle {
border.color: "#21be2b"
}
} Настройка Tumbler
Tumbler состоит из трёх визуальных элементов: фонового изображения, contentItem и делегата.
import QtQuick 2.12
import QtQuick.Controls 2.12
Tumbler {
id: control
model: 15
background: Item {
Rectangle {
opacity: control.enabled ? 0.2 : 0.1
border.color: "#000000"
width: parent.width
height: 1
anchors.top: parent.top
}
Rectangle {
opacity: control.enabled ? 0.2 : 0.1
border.color: "#000000"
width: parent.width
height: 1
anchors.bottom: parent.bottom
}
}
delegate: Text {
text: qsTr("Item %1").arg(modelData + 1)
font: control.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2)
}
Rectangle {
anchors.horizontalCenter: control.horizontalCenter
y: control.height * 0.4
width: 40
height: 1
color: "#21be2b"
}
Rectangle {
anchors.horizontalCenter: control.horizontalCenter
y: control.height * 0.6
width: 40
height: 1
color: "#21be2b"
}
} Для определения собственного элемента содержимого используйте ListView или PathView в качестве корневого элемента. Для обертывающего Tumbler используйте PathView:
Tumbler {
id: tumbler
contentItem: PathView {
id: pathView
model: tumbler.model
delegate: tumbler.delegate
clip: true
pathItemCount: tumbler.visibleItemCount + 1
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
dragMargin: width / 2
path: Path {
startX: pathView.width / 2
startY: -pathView.delegateHeight / 2
PathLine {
x: pathView.width / 2
y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
}
}
property real delegateHeight: tumbler.availableHeight / tumbler.visibleItemCount
}
} Для необорачивающего Tumbler используйте ListView:
Tumbler {
id: tumbler
contentItem: ListView {
model: tumbler.model
delegate: tumbler.delegate
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: height / 2 - (height / tumbler.visibleItemCount / 2)
preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2)
clip: true
}
}
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qtquickcontrols2-customize.html