Anpassen Qt Quick Controls

Qt Quick Controls bestehen aus einer Hierarchie (Baum) von Elementen. Um ein benutzerdefiniertes Aussehen zu erhalten, kann die standardmäßige QML-Implementierung der einzelnen Elemente durch eine benutzerdefinierte ersetzt werden.

Anpassen eines Controls

Manchmal möchten Sie ein "einmaliges" Aussehen für einen bestimmten Teil Ihrer Benutzeroberfläche schaffen und überall sonst einen vollständigen Stil verwenden. Vielleicht sind Sie mit dem Stil, den Sie verwenden, zufrieden, aber es gibt eine bestimmte Schaltfläche, die eine besondere Bedeutung hat.

Die erste Möglichkeit, diese Schaltfläche zu erstellen, besteht darin, sie einfach an Ort und Stelle zu definieren, wo sie benötigt wird. Vielleicht sind Sie zum Beispiel nicht damit zufrieden, dass die Schaltfläche des Stils Basic quadratische Ecken hat. Um sie abzurunden, können Sie das Element background überschreiben und die Radius-Eigenschaft "Rechteck" festlegen:

import QtQuick
import QtQuick.Controls.Basic

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

Hinweis: Da die verschiedenen Elemente, aus denen ein Steuerelement in einem bestimmten Stil besteht, so konzipiert sind, dass sie zusammenarbeiten, kann es notwendig sein, andere Elemente zu überschreiben, um das gewünschte Aussehen zu erhalten. Darüber hinaus können nicht alle Stile angepasst werden. Weitere Informationen finden Sie im Hinweis in der Anpassungsreferenz.

Die zweite Möglichkeit, die Schaltfläche zu erstellen, ist dann sinnvoll, wenn Sie die abgerundete Schaltfläche an mehreren Stellen verwenden möchten. Dabei wird der Code in eine eigene QML-Datei innerhalb Ihres Projekts verschoben.

Für diesen Ansatz kopieren wir den Hintergrundcode aus der Datei Button.qml des Stils Basic. Diese Datei finden Sie in Ihrer Qt-Installation unter dem folgenden Pfad:

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

Danach fügen wir einfach die folgende Zeile ein:

radius: 4

Um Verwechslungen mit den Steuerelementen im Modul selbst zu vermeiden, nennen wir die Datei MyButton.qml. Um das Steuerelement in Ihrer Anwendung zu verwenden, beziehen Sie sich auf seinen Dateinamen:

import QtQuick.Controls.Basic

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

Die dritte Möglichkeit, die Schaltfläche zu erstellen, ist etwas strukturierter, sowohl in Bezug auf die Position der Datei im Dateisystem als auch in Bezug auf ihre Verwendung in QML. Kopieren Sie zunächst eine vorhandene Datei, wie Sie es oben getan haben, aber legen Sie sie diesmal in einem Unterordner in Ihrem Projekt mit dem Namen (zum Beispiel) controls ab. Um das Steuerelement zu verwenden, importieren Sie zunächst den Ordner in einen Namensraum:

import QtQuick.Controls.Basic
import "controls" as MyControls

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

Da Sie nun den Namensraum MyControls haben, können Sie die Steuerelemente nach ihren tatsächlichen Gegenstücken im Modul Qt Quick Controls benennen. Sie können diesen Vorgang für jedes Steuerelement wiederholen, das Sie hinzufügen möchten.

Ein zusätzlicher Vorteil dieser drei Methoden ist, dass die Vorlage nicht von Grund auf neu implementiert werden muss.

Hinweis: Die drei hier genannten Methoden funktionieren nicht für die Anpassung des angehängten ToolTip, da es sich um ein intern erstelltes gemeinsames Element handelt. Um eine einmalige Anpassung eines ToolTip vorzunehmen, siehe Custom Tool Tips. Um das angehängte ToolTip anzupassen, muss es als Teil eines eigenen Stils bereitgestellt werden.

Erstellen eines benutzerdefinierten Stils

Es gibt mehrere Möglichkeiten, um eigene Stile zu erstellen. Im Folgenden werden die verschiedenen Ansätze erläutert.

Definition eines Stils

In Qt Quick Controls ist ein Stil im Wesentlichen ein Satz von QML-Dateien in einem einzigen Verzeichnis. Es gibt vier Voraussetzungen, damit ein Stil verwendet werden kann:

  • Es muss mindestens eine QML-Datei vorhanden sein, deren Name einem Steuerelement entspricht (z. B. Button.qml).
  • Jede QML-Datei muss den entsprechenden Typ aus dem QtQuick.Templates-Import als Stammelement enthalten. Zum Beispiel muss Button.qml eine Button-Vorlage als Wurzelelement enthalten.

    Wenn wir stattdessen den entsprechenden Typ aus dem QtQuick.Controls-Import verwenden würden, wie wir es im vorigen Abschnitt getan haben, würde es nicht funktionieren: das von uns definierte Steuerelement würde versuchen, von sich selbst abzuleiten.

  • Eine qmldir-Datei muss neben der/den QML-Datei(en) existieren. Im Folgenden finden Sie ein Beispiel für eine einfache qmldir Datei für einen Stil, der eine Schaltfläche bereitstellt:
    module MyStyle
    Button 2.15 Button.qml

    Wenn Sie die Stilauswahl während der Kompilierung verwenden, sollte die qmldir-Datei auch den Fallback-Stil importieren:

    # ...
    import QtQuick.Controls.Basic auto

    Dies kann auch für die Auswahl des Stils zur Laufzeit gemacht werden, anstatt z.B. QQuickStyle::setFallbackStyle() zu verwenden.

    Die Verzeichnisstruktur für einen solchen Stil sieht wie folgt aus:

    MyStyle
    ├─── Button.qml
    └─── qmldir
  • Die Dateien müssen sich in einem Verzeichnis befinden, das über den QML-Importpfad auffindbar ist.

    Wenn der Pfad zum oben genannten MyStyle-Verzeichnis beispielsweise /home/user/MyApp/MyStyle lautet, muss /home/user/MyApp zum QML-Importpfad hinzugefügt werden.

    Um MyStyle in MyApp zu verwenden, verweisen Sie auf den Namen des Verzeichnisses:

    • ./MyApp -style MyStyle

    Der Style-Name muss mit der Schreibweise des Style-Verzeichnisses übereinstimmen; die Übergabe von mystyle oder MYSTYLE wird nicht unterstützt.

Standardmäßig verwendet das Styling-System den Basic-Stil als Fallback für Steuerelemente, die nicht implementiert sind. Um einen anderen eingebauten Stil anzupassen oder zu erweitern, ist es möglich, einen anderen Fallback-Stil mit QQuickStyle anzugeben.

Das bedeutet, dass Sie so viele Steuerelemente wie gewünscht für Ihren benutzerdefinierten Stil implementieren und sie fast überall platzieren können. Außerdem können Benutzer ihre eigenen Stile für Ihre Anwendung erstellen.

Vorschau von benutzerdefinierten Stilen in Qt Quick Designer

Mit dem oben beschriebenen Ansatz ist es möglich, eine Vorschau eines benutzerdefinierten Stils in Qt Quick Designer anzuzeigen. Stellen Sie dazu sicher, dass das Projekt eine qtquickcontrols2.conf Datei hat und dass der folgende Eintrag vorhanden ist:

[Controls]
Style=MyStyle

Für weitere Informationen schauen Sie sich das Beispiel Flat Style an.

Stilspezifische C++-Erweiterungen

Manchmal müssen Sie C++ verwenden, um Ihren benutzerdefinierten Style zu erweitern.

  • Wenn der Stil, der den Typ verwendet, der einzige Stil ist, der von einer Anwendung verwendet wird, registrieren Sie den Typ bei der QML-Engine, indem Sie das Makro QML_ELEMENT hinzufügen und die Datei zum Bestandteil Ihres QML-Moduls machen:

    qt_add_qml_module(ACoolItem
        URI MyItems
        VERSION 1.0
        SOURCES
            acoolcppitem.cpp acoolcppitem.h
    )
    CONFIG += qmltypes
    QML_IMPORT_NAME = MyItems
    QML_IMPORT_MAJOR_VERSION = 1

    Wenn der Header, in dem die Klasse deklariert ist, nicht über den Include-Pfad Ihres Projekts zugänglich ist, müssen Sie möglicherweise den Include-Pfad ändern, damit der generierte Registrierungscode kompiliert werden kann.

    INCLUDEPATH += MyItems

    Weitere Informationen finden Sie unter Definieren von QML-Typen aus C++ und Erstellen einer QML-Anwendung.

  • Wenn der Stil, der den Typ verwendet, einer von vielen Stilen ist, die von einer Anwendung verwendet werden, sollten Sie erwägen, jeden Stil in ein separates Modul zu packen. Die Module werden dann bei Bedarf geladen.

Überlegungen zu benutzerdefinierten Stilen

Bei der Implementierung eines eigenen Stils und der Anpassung von Steuerelementen sind einige Punkte zu beachten, damit Ihre Anwendung so performant wie möglich ist.

Vermeiden Sie es, den Implementierungen von Elementdelegaten in Stilen eine ID zuzuweisen

Wie in Definition eines Stils erläutert, beginnen Sie bei der Implementierung Ihres eigenen Stils für ein Steuerelement mit der entsprechenden Vorlage für dieses Steuerelement. Die Button.qml eines Stils ist zum Beispiel ähnlich aufgebaut wie diese:

T.Button {
    // ...

    background: Rectangle {
        // ...
    }

    contentItem: Text {
        // ...
    }

    // ...
}

Wenn Sie in Ihrer Anwendung eine Schaltfläche verwenden, werden die Elemente background und contentItem erstellt und dem Stammelement Button übergeordnet:

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

Nehmen wir an, Sie müssen die Schaltfläche einmalig anpassen (wie in Anpassen eines Steuerelements erläutert):

import QtQuick
import QtQuick.Controls.Basic

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

In QML würde dies normalerweise dazu führen, dass sowohl die Standardimplementierung background als auch die einmaligen, benutzerdefinierten background Elemente erstellt werden. Qt Quick Controls verwendet eine Technik, die die Erstellung beider Elemente vermeidet und stattdessen nur das benutzerdefinierte background erstellt, was die Erstellungsleistung von Steuerelementen erheblich verbessert.

Diese Technik beruht auf dem Fehlen einer id in der Stilimplementierung dieses Elements. Wenn eine id zugewiesen ist, kann die Technik nicht funktionieren, und beide Elemente werden erstellt. Es kann zum Beispiel verlockend sein, background oder contentItem eine ID zuzuweisen, damit andere Objekte in der Datei auf diese Elemente verweisen können:

T.Button {
    // ...

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

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

    // ...
}

Mit diesem Code werden jedes Mal, wenn eine Button-Instanz mit einem angepassten Hintergrund erstellt wird, beide Hintergründe erstellt, was zu einer suboptimalen Erstellungsleistung führt.

Vor Qt 5.15 wurde der alte, unbenutzte Hintergrund gelöscht, um die mit ihm verbundenen Ressourcen freizugeben. Da das Steuerelement jedoch nicht Eigentümer der Elemente ist, sollte es diese nicht löschen. Seit Qt 5.15 werden alte Elemente nicht mehr gelöscht, so dass das Element backgroundRect länger lebt als nötig - typischerweise bis die Anwendung beendet wird. Obwohl das alte Element ausgeblendet, visuell vom Steuerelement entparentiert und aus dem Accessibility Tree entfernt wird, ist es wichtig, die Erstellungszeit und den Speicherverbrauch dieser unbenutzten Elemente im Auge zu behalten, wenn man in diesem Zusammenhang eine ID zuweist.

Vermeiden Sie zwingende Zuweisungen von benutzerdefinierten Elementen

Die im obigen Abschnitt erwähnte Technik funktioniert nur, wenn ein Element zum ersten Mal deklarativ zugewiesen wird, so dass imperative Zuweisungen zu verwaisten Elementen führen. Verwenden Sie, wenn möglich, immer deklarative Bindungen, um benutzerdefinierte Elemente zuzuweisen.

Importieren Sie keine QtQuick.Controls in QML-Implementierungen

Wenn Sie die QML für die Implementierung eines Steuerelements in Ihrem Stil schreiben, ist es wichtig, QtQuick.Controls nicht zu importieren. Andernfalls wird die QML vom QML-Compiler nicht kompiliert.

Implementierung von Typen, die von anderen Typen verwendet werden

Angenommen, Sie verwenden ScrollViews in Ihrer Anwendung und möchten deren Bildlaufleisten anpassen. Es ist verlockend, einfach eine benutzerdefinierte ScrollBar.qml zu implementieren und ScrollView die angepasste ScrollBar automatisch übernehmen zu lassen. Dies wird jedoch nicht funktionieren. Sie müssen sowohl ScrollBar.qml als auch ScrollView.qml implementieren.

Angehängte Eigenschaften

Es ist üblich, dass ein Stil bestimmte Eigenschaften oder Attribute hat, die für alle Steuerelemente gelten. Angehängte Eigenschaften sind eine gute Möglichkeit, ein Element in QML zu erweitern, ohne vorhandene C++, die zu diesem Element gehören, ändern zu müssen. Die Stile "Material" und "Universal" verfügen beispielsweise über eine angehängte Eigenschaft "Thema", die steuert, ob ein Element und seine untergeordneten Elemente in einem hellen oder dunklen Thema gerendert werden sollen.

Als Beispiel fügen wir eine angehängte Eigenschaft hinzu, die die Höhe steuert. Unser Stil wird die Höhe mit einem Schlagschatten darstellen; je höher die Höhe, desto größer der Schatten.

Der erste Schritt besteht darin, eine neue Qt Quick Controls Anwendung in Qt Creatorzu erstellen. Danach fügen wir einen C++-Typ hinzu, der die Höhe speichert. Da der Typ für jedes von unserem Stil unterstützte Steuerelement verwendet wird und wir später vielleicht noch weitere angehängte Eigenschaften hinzufügen möchten, nennen wir ihn MyStyle. Hier ist 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();
}

Der Typ MyStyle ist insofern etwas Besonderes, als er nicht instanziiert, sondern für seine angehängten Eigenschaften verwendet werden soll. Aus diesem Grund registrieren wir ihn auf folgende Weise in 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();
}

Wir kopieren dann Button.qml aus dem Basic-Stil in $QTDIR/qml/QtQuick/Controls/Basic/ in einen neuen Ordner myproject in unserem Projektverzeichnis. Fügen Sie das neu kopierte Button.qml zu qml.qrc hinzu, das die Ressourcendatei ist, die unsere QML-Dateien enthält.

Als Nächstes fügen wir dem Delegaten background der Schaltfläche einen Schlagschatten hinzu:

// ...
import QtQuick.Effects
import MyStyle
// ...

background: Rectangle {
    // ...

    layer.enabled: control.enabled && control.MyStyle.elevation > 0
    layer.effect: MultiEffect {
        shadowEnabled: true
        shadowHorizontalOffset: 3
        shadowVerticalOffset: 3
        shadowColor: control.visualFocus ? "#330066ff" : "#aaaaaa"
        shadowBlur: control.pressed ? 0.8 : 0.4
    }
}

Beachten Sie, dass wir:

  • Verwenden Sie den Schlagschatten nicht, wenn die Höhe der Schaltfläche 0
  • die Farbe des Schattens ändern, je nachdem, ob die Schaltfläche den Fokus hat oder nicht
  • die Größe des Schattens von der Höhe abhängig machen

Um die angehängte Eigenschaft auszuprobieren, erstellen wir eine Row mit zwei Schaltflächen in 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
        }
    }
}

Eine Schaltfläche hat keine Elevation, die andere hat eine Elevation von 10.

Damit können wir unser Beispiel ausführen. Um der Anwendung mitzuteilen, dass sie unseren neuen Stil verwenden soll, übergeben wir -style MyStyle als Anwendungsargument, aber es gibt viele Möglichkeiten, den zu verwendenden Stil anzugeben.

Das Endergebnis:

Die Anweisung import MyStyle 1.0 ist nur deshalb notwendig, weil wir die angehängte Eigenschaft von MyStyle verwenden. Beide Schaltflächen verwenden unseren benutzerdefinierten Stil, selbst wenn wir den Import entfernen würden.

Referenz für Anpassungen

Die folgenden Ausschnitte zeigen Beispiele, in denen die Steuerelemente des Stils Basic nach dem gleichen Ansatz wie im Abschnitt Anpassen eines Steuerelements angepasst wurden. Der Code kann als Ausgangspunkt für die Implementierung eines benutzerdefinierten Aussehens und Verhaltens verwendet werden.

Hinweis: Die Stile für macOS und Windows eignen sich nicht für die Anpassung. Es wird stattdessen empfohlen, ein benutzerdefiniertes Steuerelement immer auf einem einzigen Stil zu basieren, der auf allen Plattformen verfügbar ist, z. B. Basic Style, Fusion Style, Imagine Style, Material Style, Universal Style. Auf diese Weise ist gewährleistet, dass das Steuerelement immer gleich aussieht, unabhängig davon, mit welchem Stil die Anwendung ausgeführt wird. Wie Sie einen anderen Stil verwenden können, erfahren Sie unter Verwendung von Stilen in Qt Quick Controls. Alternativ können Sie auch einen eigenen Stil erstellen.

Das Anpassen von ApplicationWindow

ApplicationWindow besteht aus einem visuellen Element: background.

import QtQuick
import QtQuick.Controls.Basic

ApplicationWindow {
    visible: true

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

Die Anpassung von BusyIndicator

BusyIndicator besteht aus zwei visuellen Elementen: background und contentItem.

import QtQuick
import QtQuick.Controls.Basic

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

Schaltfläche anpassen

Die Schaltfläche besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

CheckBox besteht aus drei visuellen Elementen: background, contentItem und indicator.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

CheckDelegate besteht aus drei visuellen Elementen: background, contentItem und indicator.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

ComboBox besteht aus background, content item, popup, indicator, und delegate.

pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Controls.Basic

ComboBox {
    id: control
    model: ["First", "Second", "Third"]

    delegate: ItemDelegate {
        id: delegate

        required property var model
        required property int index

        width: control.width
        contentItem: Text {
            text: delegate.model[control.textRole]
            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
            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
        height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
        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
        }
    }
}

Wie in ComboBox Model Roles erläutert, unterstützt ComboBox mehrere Arten von Modellen.

Da alle Modelle eine anonyme Eigenschaft mit modelDatabereitstellen, ruft der folgende Ausdruck in allen Fällen den richtigen Text ab:

text: model[control.textRole]

Wenn Sie eine bestimmte textRole und ein Modell mit strukturierten Daten bereitstellen, das die ausgewählte Rolle liefert, ist dieser Ausdruck eine reguläre Eigenschaftssuche. Wenn Sie ein Modell mit singulären Daten, wie z. B. eine Liste von Strings, und ein leeres textRole bereitstellen, ruft dieser Ausdruck die modelData ab.

Anpassen von DelayButton

DelayButton besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

Wahlrad anpassen

Das Zifferblatt besteht aus zwei visuellen Elementen: background und handle.

QtQuick importierenimportieren QtQuick.Controls.BasicDial { id: control background: Rectangle { x: control.width / 2 - width / 2 y: control.height / 2 - height / 2 implicitWidth: 140 implicitHeight: 140 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: handleItemx : control.background.x + control.background.width / 2 - width / 2y : 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} ] } }

Schublade anpassen

Die Schublade kann ein visuelles background Element haben.

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

Rahmen anpassen

Der Rahmen besteht aus einem visuellen Element: background.

import QtQuick
import QtQuick.Controls.Basic

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

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

GroupBox anpassen

GroupBox besteht aus zwei visuellen Elementen: background und label.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

ItemDelegate besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

Etikett anpassen

Das Etikett kann ein visuelles Element background haben.

import QtQuick
import QtQuick.Controls.Basic

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

Menü anpassen

import QtQuick
import QtQuick.Controls.Basic

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

Menüleiste anpassen

MenuBar kann ein visuelles Element background haben, und MenuBarItem besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

PageIndicator besteht aus einem background, content item und delegate.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen des Fensters

Der Bereich besteht aus einem background.

import QtQuick
import QtQuick.Controls.Basic

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

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

Popup anpassen

Das Popup besteht aus einem background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

ProgressBar anpassen

ProgressBar besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

ProgressBar {
    id: control
    value: 0.5
    padding: 2

    background: Rectangle {
        implicitWidth: 200
        implicitHeight: 6
        color: "#e6e6e6"
        radius: 3
    }

    contentItem: Item {
        implicitWidth: 200
        implicitHeight: 4

        // Progress indicator for determinate state.
        Rectangle {
            width: control.visualPosition * parent.width
            height: parent.height
            radius: 2
            color: "#17a81a"
            visible: !control.indeterminate
        }

        // Scrolling animation for indeterminate state.
        Item {
            anchors.fill: parent
            visible: control.indeterminate
            clip: true

            Row {
                spacing: 20

                Repeater {
                    model: control.width / 40 + 1

                    Rectangle {
                        color: "#17a81a"
                        width: 20
                        height: control.height
                    }
                }
                XAnimator on x {
                    from: 0
                    to: -40
                    loops: Animation.Infinite
                    running: control.indeterminate
                }
            }
        }
    }
}

Oben ist das Inhaltselement auch animiert, um einen indeterminate Fortschrittsbalken darzustellen.

Die Anpassung von RadioButton

RadioButton besteht aus drei visuellen Elementen: background, content item und indicator.

import QtQuick
import QtQuick.Controls.Basic

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

Die Anpassung von RadioDelegate

RadioDelegate besteht aus drei visuellen Elementen: background, contentItem und indicator.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen von RangeSlider

RangeSlider besteht aus drei visuellen Elementen: background, first.handle und second.handle.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen von RoundButton

RoundButton kann auf die gleiche Weise wie Button angepasst werden.

Anpassen von ScrollBar

ScrollBar besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

Die Anpassung von ScrollIndicator

ScrollIndicator besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

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

ScrollView anpassen

ScrollView besteht aus einem Element background und horizontalen und vertikalen Bildlaufleisten.

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

Schieberegler anpassen

Slider besteht aus zwei visuellen Elementen: background, und handle.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

SpinBox besteht aus vier visuellen Elementen: background, contentItem, up indicator, und down indicator.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen von SplitView

SplitView besteht aus einem visuellen handle Delegaten.

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 anpassen

StackView kann ein visuelles Element background haben, und es ermöglicht die Anpassung der Übergänge, die für Push-, Pop- und Replace-Operationen verwendet werden.

import QtQuick
import QtQuick.Controls.Basic

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

Die Anpassung von SwipeDelegate

SwipeDelegate besteht aus sechs visuellen Elementen: background, content item, indicator, swipe.left, swipe.right und swipe.behind.

import QtQuick
import QtQuick.Controls.Basic

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

Customizing SwipeView

SwipeView kann ein visuelles Element background haben. Die Navigation wird durch das content item implementiert.

import QtQuick
import QtQuick.Controls.Basic

SwipeView {
    id: control

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

Anpassen von Switch

Switch besteht aus drei visuellen Elementen: background, content item und indicator.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen von SwitchDelegate

SwitchDelegate besteht aus drei visuellen Elementen: background, contentItem und indicator.

import QtQuick
import QtQuick.Controls.Basic

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 anpassen

TabBar besteht aus zwei visuellen Elementen: background, und contentItem.

import QtQuick
import QtQuick.Controls.Basic

TabBar {
    id: control

    background: Rectangle {
        color: "#eeeeee"
    }

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

Anpassen von TabButton

TabButton kann auf die gleiche Weise wie Button angepasst werden.

Anpassen von TextArea

TextArea besteht aus einem Element background.

import QtQuick
import QtQuick.Controls.Basic

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

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

Anpassen von TextField

TextField besteht aus einem background Element.

import QtQuick
import QtQuick.Controls.Basic

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

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

Anpassen von ToolBar

ToolBar besteht aus einem visuellen Element: background.

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

Anpassen von ToolButton

ToolButton besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

Anpassen von ToolSeparator

ToolSeparator besteht aus zwei visuellen Elementen: background und content item.

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

Anpassen von ToolTip

ToolTip besteht aus zwei visuellen Elementen: background und content item.

import QtQuick
import QtQuick.Controls.Basic

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

Hinweis: Um die attached ToolTip anzupassen, muss sie als Teil Ihres eigenen Stils bereitgestellt werden. Für eine einmalige Anpassung eines ToolTip, siehe Custom Tool Tips.

Tumbler anpassen

Tumbler besteht aus drei visuellen Elementen: background, contentItem, und delegate.

import QtQuick
import QtQuick.Controls.Basic

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
        required property int index
    }

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

Wenn Sie Ihr eigenes contentItem definieren wollen, verwenden Sie entweder ListView oder PathView als Root-Item. Für einen umhüllenden Tumbler verwenden Sie 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
    }
}

Für einen nicht umhüllenden Tumbler verwenden Sie 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
    }
}

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.