Spec-Zone.ru › Qt

Настройка Qt Quick Controls

Qt Quick Controls состоят из иерархии (дерева) элементов. Для предоставления пользовательского внешнего вида и ощущения можно заменить стандартную реализацию QML каждого элемента на пользовательскую.

Настройка элемента

Иногда вам потребуется создать уникальный внешний вид для определенной части пользовательского интерфейса и использовать общий стиль для всех остальных элементов. Возможно, вам нравится используемый стиль, но определенная кнопка имеет особое значение.

Первый способ создания такой кнопки — просто определить её на месте, где она нужна. Например, предположим, что вас не устраивают квадратные углы кнопки в стиле Basic. Чтобы сделать их закруглёнными, можно переопределить элемент background и установить свойство radius элемента Rectangle:

import QtQuick
import QtQuick.Controls

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 в вашем проекте.

Для этого подхода скопируем код background из стиля Basic's Button.qml. Этот файл можно найти по следующему пути в вашей установке Qt:

$QTDIR/qml/QtQuick/Controls/Basic/Button.qml

После этого просто добавим следующую строку:

radius: 4

Чтобы избежать путаницы с элементами в самом модуле, назовём этот файл MyButton.qml. Чтобы использовать элемент в своём приложении, ссылайтесь на него по имени файла:

import QtQuick.Controls

ApplicationWindow {
    MyButton {
        text: qsTr("A Special Button")
    }
}

Третий способ создания кнопки более структурирован, как в плане расположения файла в файловой системе, так и в плане его использования в QML. Сначала скопируйте существующий файл, как описано выше, но на этот раз поместите его в подпапку в вашем проекте, например, controls. Чтобы использовать элемент, сначала импортируйте папку в пространство имён:

import QtQuick.Controls
import "controls" as MyControls

ApplicationWindow {
    MyControls.Button {
        text: qsTr("A Special Button")
    }
}

Теперь у вас есть пространство имён MyControls, и вы можете называть элементы по их реальным аналогам в модуле Qt Quick Controls. Вы можете повторить этот процесс для любого элемента, который хотите добавить.

Дополнительное преимущество этих трёх методов состоит в том, что нет необходимости реализовывать шаблон с нуля.

Создание пользовательского стиля

Существует несколько способов создания собственных стилей. Ниже мы объясним различные подходы.

Определение стиля

В Qt Quick Controls стиль представляет собой набор файлов QML в одной директории. Для использования стиля необходимо выполнить четыре требования:

  • Должен существовать по крайней мере один файл QML, имя которого соответствует элементу (например, Button.qml) .
  • Каждый файл QML должен содержать соответствующий тип из импорта QtQuick.Templates в качестве корневого элемента. Например, Button.qml должен содержать шаблон Button в качестве корневого элемента.

    Если вместо этого мы использовали бы соответствующий тип из импорта QtQuick.Controls, как в предыдущем разделе, это не сработает: элемент, который мы определяли, будет пытаться вывести себя из себя.

  • Вместе с файлами QML должен существовать файл qmldir. Ниже приведен пример простого файла qmldir для стиля, предоставляющего кнопку:
    module MyStyle
    Button 2.15 Button.qml

    Если вы используете выбор стиля во время компиляции, файл qmldir также должен импортировать стиль по умолчанию:

    # ...
    import QtQuick.Controls.Basic auto

    Это также можно сделать для выбора стиля во время выполнения вместо использования, например, QQuickStyle::setFallbackStyle().

    Структура каталогов для такого стиля выглядит следующим образом:

    MyStyle
    ├─── Button.qml
    └─── qmldir
  • Файлы должны находиться в каталоге, который доступен через путь импорта QML.

    Например, если путь к каталогу MyStyle, упомянутому выше, был /home/user/MyApp/MyStyle, то /home/user/MyApp должен быть добавлен в путь импорта QML.

    Чтобы использовать MyStyle в MyApp, ссылайтесь на него по имени:

    • ./MyApp -style MyStyle

    Имя стиля должно соответствовать регистру каталога стиля; использование mystyle или MYSTYLE не поддерживается.

По умолчанию система стилей использует стиль Basic в качестве стиля по умолчанию для элементов, которые не реализованы. Чтобы настроить или расширить любой другой встроенный стиль, можно указать другой стиль по умолчанию с помощью 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.

Рекомендации по пользовательским стилям

При реализации собственного стиля и настройке элементов следует учитывать некоторые моменты, чтобы обеспечить максимальную производительность вашего приложения.

Избегайте присваивания идентификатора реализациям делегатов элементов в стилях

Как описано в разделе Определение стиля, при реализации собственного стиля для элемента вы начинаете с соответствующего шаблона для этого элемента. Например, структура стиля Button.qml будет похожа на эту:

T.Button {
    // ...

    background: Rectangle {
        // ...
    }

    contentItem: Text {
        // ...
    }

    // ...
}

При использовании кнопки в вашем приложении элементы background и contentItem будут созданы и добавлены в качестве потомков корневого элемента Button:

// Creates the Button root item, the Rectangle background,
// and the Text contentItem.
Button {
    text: qsTr("Confirm")
}

Предположим, что вам нужно выполнить одноразовую настройку кнопки (как описано в разделе Настройка элемента):

import QtQuick
import QtQuick.Controls

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 это обычно приводит к созданию как реализации элемента по умолчанию background, так и одноразовой пользовательской реализации background. Qt Quick Controls использует технику, которая позволяет избежать создания обоих элементов, а вместо этого создаётся только пользовательский background, что значительно улучшает производительность создания элементов.

Эта техника опирается на отсутствие идентификатора id в реализации элемента стиля. Если идентификатор задан, техника не работает, и оба элемента будут созданы. Например, может быть соблазнительно назначить идентификатор элементам background или contentItem, чтобы другие объекты в файле могли ссылаться на эти элементы:

T.Button {
    // ...

    background: Rectangle {
        id: backgroundRect
        // ...
    }

    contentItem: Text {
        // Use backgroundRect in some way...
    }

    // ...
}

С этим кодом каждый раз при создании экземпляра кнопки с настроенным фоном будут создаваться оба фона, что приводит к неэффективному использованию ресурсов при создании.

До Qt 5.15 устаревший, неиспользуемый фон удалялся для освобождения связанных с ним ресурсов. Однако, поскольку элемент не владеет элементами, он не должен их удалять. Начиная с Qt 5.15, устаревшие элементы больше не удаляются, и поэтому элемент backgroundRect будет жить дольше, чем требуется — обычно до выхода приложения. Хотя устаревший элемент будет скрыт, визуально не прикреплён к элементу и удалён из дерева доступности, важно помнить о времени создания и использовании памяти этих неиспользуемых элементов при назначении идентификатора в этом контексте.

Избегайте императивного назначения пользовательских элементов

Упомянутая выше техника работает только тогда, когда элемент декларативно назначается в первый раз, и поэтому императивные назначения приведут к появлению нежелательных элементов. Используйте декларативные связывания для назначения пользовательских элементов, когда это возможно.

Присоединённые свойства

Для стиля часто бывают свойства или атрибуты, которые применяются ко всем элементам. Присоединённые свойства — это отличный способ расширить элемент в QML, не изменяя существующий C++, принадлежащий этому элементу. Например, у стилей Material и Universal есть присоединённое свойство темы, которое управляет тем, будут ли элемент и его потомки отображаться в светлой или тёмной теме.

В качестве примера добавим присоединённое свойство, которое управляет высотой подъёма. Наш стиль проиллюстрирует подъём с помощью отбрасываемой тени; чем выше подъём, тем больше тень.

Первый шаг — создать новое приложение Qt Quick Controls в 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[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterUncreatableType<MyStyle>("MyStyle", 1, 0, "MyStyle", "MyStyle is an attached property");

    QQmlApplicationEngine engine;
    // Make the directory containing our style known to the QML engine.
    engine.addImportPath(":/");
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

Затем мы копируем Button.qml из стиля Basic в $QTDIR/qml/QtQuick/Controls/Basic/ в новую папку myproject в каталоге нашего проекта. Добавьте скопированный Button.qml в qml.qrc, который является файлом ресурсов, содержащим наши файлы QML.

Далее, мы добавляем тень к делегату фона кнопки:

// ...
import QtGraphicalEffects
import MyStyle
// ...

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
  • Изменяем цвет тени в зависимости от того, фокусирована ли кнопка
  • Зависим размер тени от возвышения

Чтобы попробовать присоединённое свойство, мы создаём ряд с двумя кнопками в main.qml:

import QtQuick
import QtQuick.Controls

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. Обе кнопки будут использовать наш пользовательский стиль, даже если мы удалим импорт.

Справочник по настройке

В следующих фрагментах представлены примеры, где элементы управления стилем Basic были настраиваются с помощью того же подхода, что и в разделе Настройка элемента управления. Код можно использовать в качестве отправной точки для реализации пользовательского вида и ощущения.

Примечание: Стили macOS и Windows не подходят для настройки. Вместо этого рекомендуется всегда базировать настраиваемый элемент управления на одном стиле, доступном на всех платформах, например, Основной стиль, Стиль Fusion, Стиль Imagine, Стиль Material, Универсальный стиль. Сделав это, вы гарантируете, что он всегда будет выглядеть одинаково независимо от используемого стилем приложения. Например:

import QtQuick.Controls.Basic as Basic

Basic.SpinBox {
    background: Rectangle { /* ... */ }
}

См. также Стиль элементов управления Qt Quick

Настройка ApplicationWindow

ApplicationWindow состоит из одного визуального элемента: фон.

import
import QtQuick.Controls

ApplicationWindow {
    visible: true

    background: Rectangle {
        gradient: Gradient {
            GradientStop { position: 0; color: "#ffffff" }
            GradientStop { position: 1; color: "#c1bbf9" }
        }
    }
}

Настройка BusyIndicator

BusyIndicator состоит из двух визуальных элементов: фон и элемент содержимого.

import QtQuick
import QtQuick.Controls

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 {
                    id: delegate
                    x: item.width / 2 - width / 2
                    y: item.height / 2 - height / 2
                    implicitWidth: 10
                    implicitHeight: 10
                    radius: 5
                    color: "#21be2b"

                    required property int index

                    transform: [
                        Translate {
                            y: -Math.min(item.width, item.height) * 0.5 + 5
                        },
                        Rotation {
                            angle: delegate.index / repeater.count * 360
                            origin.x: 5
                            origin.y: 5
                        }
                    ]
                }
            }
        }
    }
}

Настройка Кнопки

Кнопка состоит из двух визуальных элементов: фон и элемент содержимого.

import QtQuick
import QtQuick.Controls

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 состоит из трёх визуальных элементов: фон, элемент содержимого и индикатор.

import QtQuick
import QtQuick.Controls

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 состоит из трёх визуальных элементов: фон, элемент содержимого и индикатор.

import QtQuick
import QtQuick.Controls

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

ComboBox состоит из фона, элемента содержимого, поп-меню, индикатора и делегата.

import QtQuick
import QtQuick.Controls

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

        required property int 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
            function 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

DelayButton состоит из двух визуальных элементов: фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

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
                function 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()
            }
        }
    }
}

Настройка Dial

Dial состоит из двух визуальных элементов: фона и ручки.

import QtQuick
import QtQuick.Controls

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
            }
        ]
    }
}

Настройка Drawer

Drawer может иметь визуальный фон.

background: Rectangle {
    Rectangle {
        x: parent.width - 1
        width: 1
        height: parent.height
        color: "#21be2b"
    }
}

Настройка Frame

Frame состоит из одного визуального элемента: фон.

import QtQuick
import QtQuick.Controls

Frame {
    background: Rectangle {
        color: "transparent"
        border.color: "#21be2b"
        radius: 2
    }

    Label {
        text: qsTr("Content goes here!")
    }
}

Настройка GroupBox

GroupBox состоит из двух визуальных элементов: фона и метки.

import QtQuick
import QtQuick.Controls

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

ItemDelegate состоит из двух визуальных элементов: фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

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
        }
    }
}

Настройка Label

Метка может иметь визуальный фон.

import QtQuick
import QtQuick.Controls

Label {
    text: qsTr("Label")
    color: "#21be2b"
}

Настройка Меню

  • Меню состоит из визуального фона.
  • Элемент меню состоит из четырёх визуальных элементов: фон, элемент содержимого, индикатор и стрелка.
  • Разделитель меню состоит из визуального фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

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
import QtQuick.Controls

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
        }
    }
}

Настройка PageIndicator

PageIndicator состоит из фона, элемента содержимого и делегата.

import QtQuick
import QtQuick.Controls

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

        required property int index

        Behavior on opacity {
            OpacityAnimator {
                duration: 100
            }
        }
    }
}

Настройка Pane

Pane состоит из фона.

import QtQuick
import QtQuick.Controls

Pane {
    background: Rectangle {
        color: "#eeeeee"
    }

    Label {
        text: qsTr("Content goes here!")
    }
}

Настройка Popup

Popup состоит из фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

Popup {
    id: popup
    background: Rectangle {
        implicitWidth: 200
        implicitHeight: 200
        border.color: "#444"
    }
    contentItem: Column {}
}

Настройка ProgressBar

ProgressBar состоит из двух визуальных элементов: фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

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"
        }
    }
}

Настройка RadioButton

RadioButton состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.

import QtQuick
import QtQuick.Controls

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
    }
}

Настройка RadioDelegate

RadioDelegate состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.

import QtQuick
import QtQuick.Controls

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"
    }
}

Настройка RangeSlider

RangeSlider состоит из трёх визуальных элементов: фона, первой ручки и второй ручки.

import QtQuick
import QtQuick.Controls

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 + control.first.visualPosition * (control.availableWidth - width)
        y: control.topPadding + control.availableHeight / 2 - height / 2
        implicitWidth: 26
        implicitHeight: 26
        radius: 13
        color: control.first.pressed ? "#f0f0f0" : "#f6f6f6"
        border.color: "#bdbebf"
    }

    second.handle: Rectangle {
        x: control.leftPadding + control.second.visualPosition * (control.availableWidth - width)
        y: control.topPadding + control.availableHeight / 2 - height / 2
        implicitWidth: 26
        implicitHeight: 26
        radius: 13
        color: control.second.pressed ? "#f0f0f0" : "#f6f6f6"
        border.color: "#bdbebf"
    }
}

Настройка RoundButton

RoundButton можно настраивать так же, как и Кнопку.

Настройка ScrollBar

ScrollBar состоит из двух визуальных элементов: фона и элемента содержимого.

import QtQuick
import QtQuick.Controls

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"
        // Hide the ScrollBar when it's not needed.
        opacity: control.policy === ScrollBar.AlwaysOn || (control.active && control.size < 1.0) ? 0.75 : 0

        // Animate the changes in opacity (default duration is 250 ms).
        Behavior on opacity {
            NumberAnimation {}
        }
    }
}

Настройка ScrollIndicator

ScrollIndicator состоит из двух визуальных элементов: фон и элемент содержимого.

import QtQuick
import QtQuick.Controls

ScrollIndicator {
    id: control
    size: 0.3
    position: 0.2
    active: true
    orientation: Qt.Vertical

    contentItem: Rectangle {
        implicitWidth: 2
        implicitHeight: 100
        color: "#c2f4c6"
    }
}

Настройка ScrollView

ScrollView состоит из элемента фона и горизонтальной и вертикальной полос прокрутки.

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"
    }
}

Настройка Slider

Slider состоит из двух визуальных элементов: фона и кнопки.

import QtQuick
import QtQuick.Controls

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 состоит из четырёх визуальных элементов: фона, элемента содержимого, индикатора вверх и индикатора вниз.

import QtQuick
import QtQuick.Controls

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
import QtQuick.Controls

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

SwipeDelegate состоит из шести визуальных элементов: фона, элемента содержимого, индикатора, swipe.left, swipe.right, и swipe.behind.

import QtQuick
import QtQuick.Controls

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
import QtQuick.Controls

SwipeView {
    id: control

    background: Rectangle {
        color: "#eeeeee"
    }
}

Настройка Switch

Switch состоит из трёх визуальных элементов: фона, элемента содержимого и индикатора.

import QtQuick
import QtQuick.Controls

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
    }
}

Настройка SwitchDelegate

SwitchDelegate состоит из трёх визуальных элементов: фона, contentItem и индикатора.

import QtQuick
import QtQuick.Controls

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 состоит из двух визуальных элементов: фона и contentItem.

import QtQuick
import QtQuick.Controls

TabBar {
    id: control

    background: Rectangle {
        color: "#eeeeee"
    }

    TabButton {
        text: qsTr("Home")
    }
    TabButton {
        text: qsTr("Discover")
    }
    TabButton {
        text: qsTr("Activity")
    }
}

Настройка TabButton

TabButton может быть настроен таким же образом, как и кнопка.

Настройка TextArea

TextArea состоит из элемента фона.

import QtQuick
import QtQuick.Controls

TextArea {
    id: control
    placeholderText: qsTr("Enter description")

    background: Rectangle {
        implicitWidth: 200
        implicitHeight: 40
        border.color: control.enabled ? "#21be2b" : "transparent"
    }
}

Настройка TextField

TextField состоит из элемента фона.

import QtQuick
import QtQuick.Controls

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
import QtQuick.Controls

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
import QtQuick.Controls

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
import QtQuick.Controls

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)

        required property var modelData
    }

    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"
    }
}

Если вы хотите определить свой собственный contentItem, используйте 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-6.2/qtquickcontrols2-customize.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API