Auf dieser Seite

Anpassen Qt Quick Controls

Qt Quick Controls bestehen aus einer Hierarchie (Baumstruktur) von Elementen. Um ein individuelles Erscheinungsbild zu erzielen, kann die Standard-QML-Implementierung jedes Elements durch eine benutzerdefinierte ersetzt werden.

Anpassung eines Steuerelements

Manchmal möchten Sie für einen bestimmten Teil Ihrer Benutzeroberfläche ein „einzigartiges“ Erscheinungsbild erstellen und an allen anderen Stellen einen einheitlichen Stil verwenden. Vielleicht sind Sie mit dem verwendeten Stil 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 der Stelle zu definieren, an der sie benötigt wird. Beispielsweise sind Sie vielleicht nicht damit zufrieden, dass die Schaltfläche des „Basic“-Stils eckige Ecken hat. Um sie abzurunden, können Sie das Element „ background “ überschreiben und die Eigenschaft „radius“ von „Rectangle“ 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 sich ein Steuerelement in einem bestimmten Stil zusammensetzt, so konzipiert sind, dass sie zusammenwirken, kann es erforderlich sein, weitere Elemente zu überschreiben, um das gewünschte Erscheinungsbild zu erzielen. Außerdem lassen sich nicht alle Stile anpassen. Weitere Informationen finden Sie im Hinweis in der Referenz zur Anpassung.

Die zweite Methode zum Erstellen der Schaltfläche eignet sich gut, wenn Sie Ihre 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 befindet sich in Ihrer Qt-Installation unter folgendem Pfad:

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

Anschließend fügen wir einfach die folgende Zeile hinzu:

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, verweisen Sie mit dem Dateinamen darauf:

import QtQuick.Controls.Basic

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

Die dritte Möglichkeit, die Schaltfläche zu erstellen, ist etwas strukturierter, sowohl hinsichtlich des Speicherorts der Datei im Dateisystem als auch hinsichtlich ihrer Verwendung in QML. Kopieren Sie zunächst wie oben beschrieben eine vorhandene Datei, legen Sie sie diesmal jedoch in einem Unterordner Ihres Projekts ab, der beispielsweise den Namen „ controls “ trägt. 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 über den Namensraum „ MyControls “ verfügen, können Sie die Steuerelemente nach ihren tatsächlichen Entsprechungen im Modul „ Qt Quick Controls “ benennen. Sie können diesen Vorgang für jedes Steuerelement wiederholen, das Sie hinzufügen möchten.

Ein weiterer Vorteil dieser drei Methoden besteht darin, dass die Vorlage nicht von Grund auf neu implementiert werden muss.

Hinweis: Die drei hier genannten Ansätze funktionieren nicht für die Anpassung des angehängten „ ToolTip “, da es sich dabei um ein intern erstelltes gemeinsames Element handelt. Informationen zur einmaligen Anpassung eines „ ToolTip “ finden Sie unter Custom Tool Tips. Um das angehängte „ ToolTip “ anzupassen, muss es als Teil Ihres eigenen Stils bereitgestellt werden.

Erstellen eines benutzerdefinierten Stils

Es gibt verschiedene Möglichkeiten, eigene Stile zu erstellen. Im Folgenden erläutern wir die verschiedenen Ansätze.

Definition eines Stils

In „ Qt Quick Controls “ ist ein Stil im Wesentlichen eine Sammlung von QML-Dateien in einem einzigen Verzeichnis. Damit ein Stil verwendet werden kann, müssen vier Voraussetzungen erfüllt sein:

  • Es muss mindestens eine QML-Datei vorhanden sein, deren Name mit einem Steuerelement übereinstimmt (zum Beispiel „ Button.qml “).
  • Jede QML-Datei muss den entsprechenden Typ aus dem Import „QtQuick.Templates“ als Stammelement enthalten. Beispielsweise muss „Button.qml“ eine „Button“-Vorlage als Stammelement enthalten.

    Würden wir stattdessen, wie im vorherigen Abschnitt, den entsprechenden Typ aus dem Import „QtQuick.Controls“ verwenden, würde dies nicht funktionieren: Das von uns definierte Steuerelement würde versuchen, von sich selbst abzuleiten.

  • Neben der/den QML-Datei(en) muss eine „qmldir“-Datei vorhanden sein. Nachfolgend 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 zur Kompilierungszeit verwenden, sollte die `qmldir`-Datei auch den Fallback-Stil importieren:

    # ...
    import QtQuick.Controls.Basic auto

    Dies ist auch bei der Laufzeit-Stilauswahl möglich, anstatt beispielsweise 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 Verzeichnis „MyStyle“ beispielsweise /home/user/MyApp/MyStyle lautet, muss /home/user/MyApp zum QML-Importpfad hinzugefügt werden.

    Um „MyStyle“ in „MyApp“ zu verwenden, verweisen Sie mit dem Namen darauf:

    • ./MyApp -style MyStyle

    Der Stilname muss der Groß-/Kleinschreibung des Stilverzeichnisses entsprechen; 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 integrierten Stil anzupassen oder zu erweitern, kann mithilfe von ` QQuickStyle` ein anderer Fallback-Stil angegeben werden.

Das bedeutet, dass Sie für Ihren benutzerdefinierten Stil beliebig viele Steuerelemente implementieren und diese fast überall platzieren können. Außerdem können Benutzer auf diese Weise eigene Stile für Ihre Anwendung erstellen.

Vorschau benutzerdefinierter Stile im „ Qt Quick Designer“

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

[Controls]
Style=MyStyle

Weitere Informationen finden Sie im Beispiel „Flat Style“.

Stilspezifische C++-Erweiterungen

Manchmal kann es erforderlich sein, C++ zu verwenden, um Ihren benutzerdefinierten Stil zu erweitern.

  • Wenn der Stil, der den Typ verwendet, der einzige Stil ist, der von einer Anwendung genutzt wird, registrieren Sie den Typ bei der QML-Engine, indem Sie das Makro „ QML_ELEMENT “ hinzufügen und die Datei in Ihr QML-Modul integrieren:

    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

    Falls die Header-Datei, in der die Klasse deklariert ist, über den Include-Pfad Ihres Projekts nicht zugänglich ist, müssen Sie den Include-Pfad möglicherweise anpassen, 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 genutzt werden, sollten Sie in Erwägung ziehen, 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 sollten Sie einige Punkte beachten, um sicherzustellen, dass Ihre Anwendung so leistungsfähig wie möglich ist.

Vermeiden Sie es, den Implementierungen von Element-Delegaten in Stilen eine ID zuzuweisen

Wie unter „Definition eines Stils“ erläutert, gehen Sie bei der Implementierung eines eigenen Stils für ein Steuerelement von der entsprechenden Vorlage für dieses Steuerelement aus. Beispielsweise ist die Datei „ Button.qml “ eines Stils in etwa wie folgt aufgebaut:

T.Button {
    // ...

    background: Rectangle {
        // ...
    }

    contentItem: Text {
        // ...
    }

    // ...
}

Wenn Sie in Ihrer Anwendung eine Schaltfläche (Button) verwenden, werden die Elemente „ background “ und „ contentItem “ erstellt und dem Stammelement „ Button “ untergeordnet:

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

Angenommen, Sie müssten dann eine einmalige Anpassung der Schaltfläche vornehmen (wie unter „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 das einmalige, benutzerdefinierte Element „ background “ erstellt werden. „ Qt Quick Controls “ nutzt eine Technik, die die Erstellung beider Elemente vermeidet und stattdessen nur das benutzerdefinierte Element „ background “ erstellt, wodurch die Erstellungsleistung von Steuerelementen erheblich verbessert wird.

Diese Technik setzt voraus, dass in der Stilimplementierung dieses Elements keine ID vorhanden ist. Wird eine ID zugewiesen, funktioniert die Technik nicht, und beide Elemente werden erstellt. So kann es beispielsweise verlockend sein, dem „ background “ oder dem „ contentItem “ eine ID zuzuweisen, damit andere Objekte innerhalb 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 Erstellungleistung führt.

Vor Qt 5.15 wurde der alte, nicht mehr verwendete Hintergrund gelöscht, um die damit verbundenen Ressourcen freizugeben. Da das Steuerelement jedoch nicht Eigentümer der Elemente ist, sollte es diese nicht löschen. Ab Qt 5.15 werden alte Elemente nicht mehr gelöscht, sodass das Element „ backgroundRect “ länger bestehen bleibt, als nötig – in der Regel bis zum Beenden der Anwendung. Obwohl das alte Element ausgeblendet, visuell vom Steuerelement getrennt und aus dem Barrierefreiheitsbaum entfernt wird, ist es wichtig, die Erstellungszeit und den Speicherverbrauch dieser ungenutzten Elemente zu berücksichtigen, wenn in diesem Kontext eine ID zugewiesen wird.

Vermeiden Sie imperative Zuweisungen benutzerdefinierter Elemente

Die im obigen Abschnitt erwähnte Technik funktioniert nur, wenn ein Element zum ersten Mal deklarativ zugewiesen wird; imperativische Zuweisungen führen daher zu verwaisten Elementen. Verwenden Sie nach Möglichkeit immer deklarative Bindungen, um benutzerdefinierte Elemente zuzuweisen.

Importieren Sie „QtQuick.Controls“ nicht in QML-Implementierungen

Beim Schreiben des QML-Codes für die Implementierung eines Steuerelements in Ihrem Stil ist es wichtig, „ QtQuick.Controls “ nicht zu importieren. Andernfalls kann der QML-Compiler den QML-Code nicht kompilieren.

Implementieren Sie Typen, die von anderen Typen verwendet werden

Angenommen, Sie verwenden in Ihrer Anwendung `ScrollViews` und möchten deren Bildlaufleisten anpassen. Es ist verlockend, einfach eine benutzerdefinierte ` ScrollBar.qml` zu implementieren und darauf zu vertrauen, dass ` ScrollView ` die angepasste ` ScrollBar ` automatisch übernimmt. Dies funktioniert jedoch nicht. Sie müssen sowohl ` ScrollBar.qml ` als auch ` ScrollView.qml` implementieren.

Angehängte Eigenschaften

Es ist üblich, dass ein Stil bestimmte Eigenschaften oder Attribute aufweist, die für alle Steuerelemente gelten. Angehängte Eigenschaften sind eine hervorragende Möglichkeit, ein Element in QML zu erweitern, ohne den zugehörigen bestehenden C++-Code ändern zu müssen. Beispielsweise verfügen sowohl der Material- als auch der Universal-Stil über eine angehängte „theme“-Eigenschaft, die steuert, ob ein Element und seine untergeordneten Elemente in einem hellen oder dunklen Design dargestellt werden.

Fügen wir als Beispiel eine angehängte Eigenschaft hinzu, die die Höhe steuert. Unser Stil wird die Höhe durch einen Schlagschatten veranschaulichen; je höher die Höhe, desto größer der Schatten.

Der erste Schritt besteht darin, eine neue „ Qt Quick Controls “-Anwendung unter Qt Creator oder unter Qt Extension for Visual Studio Code zu erstellen. Anschließend fügen wir einen C++-Typ hinzu (unter Qt Creator oder unter Qt Extension for Visual Studio Code), der die „Elevation“ speichert. Da der Typ für jedes von unserem Stil unterstützte Steuerelement verwendet wird und wir später möglicherweise 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 besonders, als er nicht instanziiert werden sollte, sondern vielmehr für seine zugehörigen Eigenschaften verwendet wird. 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();
}

Anschließend kopieren wir „ Button.qml “ aus dem Stil „Basic“ in „ $QTDIR/qml/QtQuick/Controls/Basic/ “ in einen neuen Ordner „ myproject “ in unserem Projektverzeichnis. Fügen Sie die neu kopierte Datei „ Button.qml “ zu „ qml.qrc “ hinzu, der Ressourcendatei, die unsere QML-Dateien enthält.

Als Nächstes fügen wir dem Delegaten „ background “ des Buttons 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:

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

Um die angehängte Eigenschaft auszuprobieren, erstellen wir in „ main.qml “ ein „ Row “ mit zwei Schaltflächen:

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 Erhebung, die andere hat eine Erhebung von „ 10 “.

Nachdem dies eingerichtet ist, können wir unser Beispiel ausführen. Um der Anwendung mitzuteilen, dass sie unseren neuen Stil verwenden soll, übergeben wir „ -style MyStyle “ als Anwendungsargument; es gibt jedoch viele Möglichkeiten, den zu verwendenden Stil anzugeben.

Das Endergebnis:

Individuell gestaltete Schaltflächen

Beachten Sie, dass die Anweisung „ import MyStyle 1.0 “ nur deshalb erforderlich ist, 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 zur Anpassung

Die folgenden Codeausschnitte zeigen Beispiele, bei denen die Steuerelemente des „Basic“-Stils nach dem gleichen Ansatz wie im Abschnitt „Anpassen eines Steuerelements“ angepasst wurden. Der Code kann als Ausgangspunkt für die Implementierung eines benutzerdefinierten Erscheinungsbilds dienen.

Hinweis: Die Stile „macOS“ und „Windows“ eignen sich nicht für die Anpassung. Es wird stattdessen empfohlen, ein angepasstes Steuerelement stets auf einem einzigen Stil aufzubauen, der auf allen Plattformen verfügbar ist, z. B. „Basic Style“, „Fusion Style“, „Imagine Style“, „Material Style“ oder „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. Informationen zur Verwendung eines anderen Stils finden Sie unter „Verwenden von Stilen“ unter Qt Quick Controls. Alternativ können Sie auch einen eigenen Stil erstellen.

Hinweis: Beim Ändern der Größe von Steuerelementen bleibt die tatsächliche Inhaltsgröße in der Regel unverändert. Beispielsweise können einige Stile dafür sorgen, dass ihre Schaltfläche die Grenzen des Steuerelements ausfüllt, das Kontrollkästchen und der Text eines „ CheckBox “ jedoch horizontal und/oder vertikal zentriert werden. Wenn das standardmäßige Verhalten bei der Größenanpassung nicht gewünscht ist, überschreiben Sie die entsprechenden Delegaten.

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

Anpassung von „BusyIndicator“

BusyIndicator besteht aus zwei visuellen Elementen: background und contentItem.

Indikator für „Beschäftigt“ im benutzerdefinierten Stil

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

Anpassen der Schaltfläche

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

Individuell gestaltete Schaltfläche

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

Anpassen des Kontrollkästchens

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

Individuell gestaltetes Kontrollkästchen

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 {
            Breite: 14
            Höhe: 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
       Farbe: control.down? "#17a81a": "#21be2b"
        vertikale Ausrichtung: Text.AlignVCenter
        Abstand links: control.indicator.width + control.spacing
    }
}

Anpassen von CheckDelegate

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

Benutzerdefinierter Check-Delegat

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

Anpassung von „ComboBox“

ComboBox besteht aus background, contentItem, popup, indicator und delegate.

Benutzerdefiniertes Kombinationsfeld

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 unter ComboBox Model Roles erläutert, unterstützt ComboBox mehrere Modelltypen.

Da alle Modelle eine anonyme Eigenschaft mit dem Namen „ modelData “ bereitstellen, liefert der folgende Ausdruck in allen Fällen den richtigen Text:

text: model[control.textRole]

Wenn Sie ein bestimmtes ` textRole ` und ein Modell mit strukturierten Daten angeben, das die ausgewählte Rolle bereitstellt, handelt es sich bei diesem Ausdruck um eine reguläre Eigenschaftssuche. Wenn Sie ein Modell mit singulären Daten, wie beispielsweise einer Liste von Zeichenfolgen, und ein leeres ` textRole` angeben, ruft dieser Ausdruck die Eigenschaft ` modelData` ab.

Anpassen von „DelayButton“

DelayButton besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Individuell gestaltete Verzögerungstaste

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

Anpassen von „Dial“

„Dial“ besteht aus zwei visuellen Elementen: background und handle.

Individuell gestaltetes Zifferblatt

import QtQuick
import QtQuick.Controls.Basic

Dial {
    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: 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
            }
        ]
    }
}

Anpassung der DoubleSpinBox

DoubleSpinBox kann auf dieselbe Weise wie ein Button angepasst werden.

Anpassen von „Drawer“

„Drawer“ kann ein Element namens „Visual background “ enthalten.

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

Anpassung des Rahmens

Der Rahmen besteht aus einem visuellen Element: „ background “.

Individuell gestalteter Rahmen

import QtQuick
import QtQuick.Controls.Basic

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

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

Anpassen von GroupBox

GroupBox besteht aus zwei visuellen Elementen: „ background “ und „ label “.

Gruppenfeld mit benutzerdefiniertem Design

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

Anpassung von „ItemDelegate“

ItemDelegate besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Benutzerdefinierter Delegat für Elemente

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

Anpassen von „Label“

Ein Label kann ein visuelles „ background “-Element enthalten.

Individuell gestaltetes Etikett

import QtQuick
import QtQuick.Controls.Basic

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

Anpassung von „Menu“

Individuell gestaltetes Menü

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

Anpassen der Menüleiste

MenuBar kann ein visuelles Element „ background “ enthalten, und „ MenuBarItem “ besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Individuell gestaltete Menüleiste mit den Menüs „Datei“ und „Bearbeiten“

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

Anpassung von „PageIndicator“

PageIndicator besteht aus einem „ background “, einem „ contentItem “ und einem „ delegate “.

Individuell gestaltete Seitenanzeige für mehrere Seiten

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

Anpassung des Bereichs

Der Bereich besteht aus einem „ background “.

Individuell gestaltete Scheibe mit dekorativem Hintergrund

import QtQuick
import QtQuick.Controls.Basic

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

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

Anpassung des Popups

Das Popup besteht aus einem „ background “ und einem „ contentItem “.

Individuell gestaltetes Popup-Fenster mit Rahmen und Schatten

import QtQuick
import QtQuick.Controls.Basic

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

Anpassung der ProgressBar

ProgressBar besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Individuell gestalteter Fortschrittsbalken, der den teilweisen Fertigstellungsgrad anzeigt

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 wird das „contentItem“ ebenfalls animiert, um den Status eines „ indeterminate “-Fortschrittsbalkens darzustellen.

Anpassen des RadioButton

RadioButton besteht aus drei visuellen Elementen: „ background “, „ contentItem “ und „ indicator “.

Individuell gestaltetes Optionsfeld im ausgewählten Zustand

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

Anpassung von RadioDelegate

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

Benutzerdefinierter Radio-Delegate in einer Liste

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

Anpassung von „RangeSlider“

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

Individuell gestalteter Bereichsregler

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

Anpassung von „RoundButton“

RoundButton kann auf dieselbe Weise wie „Button“ angepasst werden.

Anpassen von „ScrollBar“

ScrollBar besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Individuell gestaltete Bildlaufleiste

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

Anpassung von „ScrollIndicator“

ScrollIndicator besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

Indikator für den Bildlauf mit benutzerdefiniertem Design

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

Anpassen von „ScrollView“

ScrollView besteht aus einem „ background “-Element sowie horizontalen und vertikalen Bildlaufleisten.

Individuell gestaltete Scroll-Ansicht

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

Anpassen des „Slider“

Der „Slider“ besteht aus zwei visuellen Elementen: „ background “ und „ handle “.

Individuell gestalteter Slider

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

Anpassen der SpinBox

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

Individuell gestaltetes Auswahllfeld

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

Anpassung von SplitView

SplitView besteht aus einem visuellen „ handle “-Delegaten.

Individuell gestaltete geteilte Ansicht

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

Anpassung von „StackView“

StackView kann ein visuelles „ background “-Element enthalten und 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
        }
    }
}

Anpassen von SwipeDelegate

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

Benutzerdefinierter Swipe-Delegate

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

Anpassen von SwipeView

SwipeView kann ein visuelles „ background “-Element enthalten. Die Navigation wird über die Klasse contentItem implementiert.

import QtQuick
import QtQuick.Controls.Basic

SwipeView {
    id: control

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

Anpassen von „Switch“

„Switch“ besteht aus drei visuellen Elementen: „ background “, „ contentItem “ und „ indicator “.

Individuell gestalteter Schalter

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

Anpassung von „SwitchDelegate“

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

Benutzerdefinierter Switch-Delegat

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

Anpassung von „TabBar“

TabBar besteht aus zwei visuellen Elementen: background und contentItem.

Individuell gestaltete Registerkartenleiste

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 dieselbe Weise wie ein Button angepasst werden.

Anpassen von „TextArea“

TextArea besteht aus einem „ background “-Element.

Textbereich mit benutzerdefiniertem Stil

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.

Textfeld mit benutzerdefiniertem Stil

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

Anpassung der „ToolBar“

ToolBar besteht aus einem visuellen Element: „ background “.

Individuell gestaltete Symbolleiste

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 „ contentItem “.

Individuell gestaltete Werkzeugschaltfläche

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 contentItem.

Individuell gestalteter Werkzeug-Trennbalken

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

Anpassung von „ToolTip“

ToolTip besteht aus zwei visuellen Elementen: „ background “ und „ contentItem “.

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 das „ attached ToolTip “ anzupassen, muss es als Teil Ihres eigenen Stils bereitgestellt werden. Informationen zur einmaligen Anpassung eines „ ToolTip “ finden Sie unter Custom Tool Tips.

Anpassen von Tumbler

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

Tumbler im individuellen Design

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 ein eigenes „contentItem“ definieren möchten, verwenden Sie entweder ein „ ListView “ oder ein „ PathView “ als Stammelement. Für einen Tumbler mit Zeilenumbruch 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 Tumbler ohne Umbruch 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
    }
}

Anpassen von „TableViewDelegate“

TableViewDelegate erbt von ` ItemDelegate`, was bedeutet, dass er aus zwei visuellen Elementen besteht: ` background ` und ` contentItem`.

Sie können „ editDelegate “ jederzeit einen eigenen, benutzerdefinierten Bearbeitungsdelegaten zuweisen, wenn Sie Anforderungen haben, die über die Möglichkeiten des Standard-Bearbeitungsdelegaten hinausgehen.

Benutzerdefinierter Delegat für die Tabellenansicht

delegate: TableViewDelegate {
    id: tableCell

    checked: column === 0 ? checkBox.checked : tableView.itemAtIndex(tableView.index(row, 0)).checked
    selected: checked

    background: Item {
        Rectangle {
            anchors.fill: parent
            anchors.margins: tableCell.current ? 3 : 1
            color: tableCell.selected ? "blue" : "white"
        }

        Rectangle {
            anchors.fill: parent
            color: "transparent"
            border.color: "darkblue"
            border.width: tableCell.current ? 2 : 0
        }
    }

    contentItem: Item {
        implicitHeight: 40
        visible: !tableCell.editing

        RowLayout {
            anchors.fill: parent

            CheckBox {
                id: checkBox
                implicitWidth: height
                Layout.fillHeight: true
                checked: false
                visible: tableCell.column === 0
            }

            Text {
                Layout.leftMargin: 4
                Layout.fillWidth: true
                Layout.fillHeight: true
                verticalAlignment: Text.AlignVCenter
                color: tableCell.selected ? "white" : "black"
                text: tableCell.model.display
            }
        }
    }

    TableView.editDelegate: FocusScope {
        width: parent.width
        height: parent.height

        TableView.onCommit: {
            let qaim = tableCell.tableView.model
            if (!qaim)
                return
            const index = qaim.index(tableCell.row, tableCell.column)
            // instead of the edit role, any custom role supported by the model can be checked
            // e.g. if (!tableCell.checked || !tableCell.model.customRole)
            if (!tableCell.checked || !tableCell.model.edit)
                return
            // instead of the edit role, any custom role supported by the model can be set
            // e.g. tableCell.model.customRole = textField.text
            tableCell.model.edit = textField.text
            tableCell.model.display = textField.text
        }

        Component.onCompleted: textField.selectAll()

        TextField {
            id: textField
            anchors.fill: parent
            text: tableCell.model.edit ?? tableCell.model.display ?? ""
            focus: true
        }
    }
}

Anpassen von „HeaderViewDelegate“

„HeaderViewDelegate“ erbt von „ TableViewDelegate “, was bedeutet, dass es aus zwei Elementen besteht: „ background “ und „ contentItem “. Sie können diese jederzeit mit beliebigen Elementen anpassen.

Benutzerdefinierter Delegat für die Kopfzeilenansicht

Hier ist ein Beispiel für die Anpassung des Delegaten für die horizontale Kopfzeilenansicht:

delegate: HorizontalHeaderViewDelegate {
    id: horizontalDelegate

    required property int index
    required property string modelData

    background: Rectangle {
        height: horizontalDelegate.height
        color: columnCheckBox.checked ? palette.highlight : palette.base
        radius: 8
    }

    contentItem: Item {
        implicitWidth: columnCheckBox.implicitWidth * 2
        implicitHeight: 40

        CheckBox {
            id: columnCheckBox
            anchors.centerIn: parent
            text: horizontalDelegate.modelData
            Component.onCompleted: checked = horizontalDelegate.index === 1
        }
    }
}

Hier ist ein Beispiel für die Anpassung des vertikalen Header-View-Delegaten:

delegate: VerticalHeaderViewDelegate {
    id: verticalDelegate

    required property int index

    background: Rectangle {
        height: verticalDelegate.height
        color: palette.base
        border.width: rowCheckBox.checked ? 2 : 0
        border.color: palette.highlight
        radius: 8
    }

    contentItem: Item {
        implicitWidth: rowCheckBox.implicitWidth * 2
        implicitHeight: 40

        CheckBox {
            id: rowCheckBox
            anchors.centerIn: parent
            text: verticalDelegate.index + 1
            Component.onCompleted: checked = verticalDelegate.index % 3 === 0
        }
    }
}

Gestaltung von Steuerelementen mit StyleKit

Das Qt Labs StyleKit-Modul bietet eine Reihe von QML-Typen zur Gestaltung von Qt Quick Controls, die auf Qt Quick Templates 2 aufsetzen. Damit können Sie einen vollständigen visuellen Stil für alle Ihre Steuerelemente über ein einziges Style-Objekt definieren, einschließlich der Unterstützung für Themen, zustandsbasierte Gestaltung und Übergänge. StyleKit übernimmt automatisch die zugrunde liegende Template-Implementierung, sodass Sie sich ganz auf visuelle Aspekte wie Farben, Abmessungen, Rahmen und Schatten konzentrieren können.

Das Qt Labs StyleKit -Modul ist ein Technology Preview-Modul in Qt 6.11.

© 2026 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.