Personnalisation Qt Quick Controls
Qt Quick Controls sont organisés selon une hiérarchie (arborescence) d’éléments. Afin de personnaliser l’apparence et le comportement, l’implémentation QML par défaut de chaque élément peut être remplacée par une implémentation personnalisée.
Personnalisation d'un contrôle
Il vous arrivera parfois de vouloir créer un style « unique » pour une partie spécifique de votre interface utilisateur, tout en conservant un style identique partout ailleurs. Peut-être êtes-vous satisfait du style que vous utilisez, mais un bouton particulier revêt une importance particulière.
La première façon de créer ce bouton consiste simplement à le définir directement à l’endroit où vous en avez besoin. Par exemple, vous n’êtes peut-être pas satisfait des coins carrés du bouton du style « Basic ». Pour les arrondir, vous pouvez redéfinir l’élément « background » et définir la propriété « radius » du rectangle :
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
}
}
}Remarque : les différents éléments qui composent un contrôle dans un style donnéétant conçus pour fonctionner ensemble, il peut s’avérer nécessaire de redéfinir d’autres éléments pour obtenir l’apparence souhaitée. De plus, tous les styles ne peuvent pas être personnalisés. Consultez la remarque dans la Référence de personnalisation pour plus d’informations.
La deuxième méthode de création du bouton est recommandée si vous prévoyez d’utiliser votre bouton aux coins arrondis à plusieurs endroits. Elle consiste à déplacer le code dans son propre fichier QML au sein de votre projet.
Pour cette approche, nous allons copier le code d'arrière-plan à partir du fichier ` Button.qml` du style « Basic ». Ce fichier se trouve à l'emplacement suivant dans votre installation Qt :
$QTDIR/qml/QtQuick/Controls/Basic/Button.qml
Une fois cela fait, il suffit d'ajouter la ligne suivante :
radius: 4Pour éviter toute confusion avec les contrôles du module lui-même, nous nommerons le fichier « MyButton.qml ». Pour utiliser ce contrôle dans votre application, faites-y référence par son nom de fichier :
import QtQuick.Controls.Basic
ApplicationWindow {
MyButton {
text: qsTr("A Special Button")
}
}La troisième méthode pour créer le bouton est un peu plus structurée, tant au niveau de l’emplacement du fichier dans le système de fichiers que de son utilisation dans QML. Commencez par copier un fichier existant comme vous l'avez fait ci-dessus, mais cette fois-ci, placez-le dans un sous-dossier de votre projet nommé (par exemple) controls. Pour utiliser le contrôle, importez d'abord le dossier dans un espace de noms :
import QtQuick.Controls.Basic
import "controls" as MyControls
ApplicationWindow {
MyControls.Button {
text: qsTr("A Special Button")
}
}Comme vous disposez désormais de l'espace de noms MyControls, vous pouvez nommer les contrôles d'après leurs équivalents réels dans le module Qt Quick Controls. Vous pouvez répéter ce processus pour tout contrôle que vous souhaitez ajouter.
L'un des avantages supplémentaires de ces trois méthodes est qu'il n'est pas nécessaire d'implémenter le modèle à partir de zéro.
Remarque : les trois approches mentionnées ici ne fonctionnent pas pour personnaliser l’ ToolTip joint, car il s’agit d’un élément partagé créé en interne. Pour effectuer une personnalisation ponctuelle d’un ToolTip, consultez Custom Tool Tips. Pour personnaliser l’ ToolTip joint, celui-ci doit être fourni dans le cadre de votre propre style.
Création d’un style personnalisé
Il existe plusieurs façons de créer vos propres styles. Nous vous expliquons ci-dessous les différentes approches.
Définition d'un style
Dans Qt Quick Controls, un style est essentiellement un ensemble de fichiers QML situés dans un même répertoire. Pour qu’un style soit utilisable, il doit répondre à quatre conditions :
- Il doit exister au moins un fichier QML dont le nom correspond à un contrôle (par exemple,
Button.qml). - Chaque fichier QML doit contenir, en tant qu’élément racine, le type correspondant issu de l’importation QtQuick.Templates. Par exemple, le fichier Button.qml doit contenir un modèle Button comme élément racine.
Si nous utilisions à la place le type correspondant issu de l’importation QtQuick.Controls, comme nous l’avons fait dans la section précédente, cela ne fonctionnerait pas : le contrôle que nous définissons tenterait de dériver de lui-même.
- Un fichier qmldir doit exister aux côtés du ou des fichiers QML. Voici un exemple de fichier
qmldirsimple pour un style fournissant un bouton :module MyStyle Button 2.15 Button.qmlSi vous utilisez la sélection de style à la compilation, le fichier `qmldir` doit également importer le style de secours :
# ... import QtQuick.Controls.Basic autoCela peut également être fait pour la sélection de style à l'exécution au lieu d'utiliser, par exemple, ` QQuickStyle::setFallbackStyle()`.
La structure de répertoires pour un tel style se présente comme suit :
MyStyle ├─── Button.qml └─── qmldir - Les fichiers doivent se trouver dans un répertoire accessible via le chemin d'importation QML.
Par exemple, si le chemin d'accès au répertoire MyStyle mentionné ci-dessus est
/home/user/MyApp/MyStyle, alors/home/user/MyAppdoit être ajouté au chemin d'importation QML.Pour utiliser MyStyle dans MyApp, faites-y référence par son nom :
./MyApp -style MyStyle
Le nom du style doit respecter la casse du répertoire du style ; l'utilisation de « mystyle » ou « MYSTYLE » n'est pas prise en charge.
Par défaut, le système de styles utilise le style « Basic » comme style de secours pour les contrôles qui ne sont pas implémentés. Pour personnaliser ou étendre tout autre style intégré, il est possible de spécifier un style de secours différent à l’aide de ` QQuickStyle`.
Cela signifie que vous pouvez implémenter autant de contrôles que vous le souhaitez pour votre style personnalisé, et les placer pratiquement n'importe où. Cela permet également aux utilisateurs de créer leurs propres styles pour votre application.
Aperçu des styles personnalisés dans le concepteur d’ Qt Quick
En suivant la méthode décrite ci-dessus, il est possible de prévisualiser un style personnalisé dans le concepteur d'Qt Quick. Pour ce faire, assurez-vous que le projet contient un fichier qtquickcontrols2.conf et que l'entrée suivante y figure :
[Controls]
Style=MyStylePour plus d’informations, consultez l’ exemple « Flat Style ».
Extensions C++ spécifiques aux styles
Il peut parfois s'avérer nécessaire d'utiliser le C++ pour étendre votre style personnalisé.
- Si le style utilisant ce type est le seul utilisé par une application, enregistrez ce type auprès du moteur QML en ajoutant la macro ` QML_ELEMENT ` et en intégrant le fichier à votre module QML : `
`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 = 1Si l'en-tête dans lequel la classe est déclarée n'est pas accessible depuis le chemin d'inclusion de votre projet, vous devrez peut-être modifier ce chemin afin que le code d'enregistrement généré puisse être compilé.
INCLUDEPATH += MyItemsPour plus d’informations, consultez les sections « Définition de types QML depuis C++ » et « Création d’une application QML ».
- Si le style utilisant ce type fait partie des nombreux styles utilisés par une application, envisagez de placer chaque style dans un module distinct. Les modules seront alors chargés à la demande.
Considérations relatives aux styles personnalisés
Lorsque vous implémentez votre propre style et personnalisez des contrôles, certains points doivent être pris en compte pour garantir que votre application soit aussi performante que possible.
Évitez d'attribuer un identifiant aux implémentations des délégués d'élément dans les styles
Comme expliqué dans la section « Définition d'un style », lorsque vous implémentez votre propre style pour un contrôle, vous partez du modèle correspondant à ce contrôle. Par exemple, l'Button.qml e d'un style sera structurée de la manière suivante :
Lorsque vous utilisez un bouton (Button) dans votre application, les éléments « background » et « contentItem » seront créés et rattachés à l’élément racine « Button » :
// Creates the Button root item, the Rectangle background,
// and the Text contentItem.
Button {
text: qsTr("Confirm")
}Supposons que vous deviez ensuite effectuer une personnalisation ponctuelle du bouton (comme expliqué dans la section « Personnalisation d’un contrôle ») :
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
}
}
}En QML, cela entraînerait normalement la création à la fois de l’implémentation par défaut background et de l’élément personnalisé ponctuel background. Qt Quick Controls utilise une technique qui évite de créer ces deux éléments et ne crée à la place que l’élément personnalisé background, ce qui améliore considérablement les performances de création des contrôles.
Cette technique repose sur l’absence d’identifiant (id) dans l’implémentation du style de cet élément. Si un identifiant est attribué, la technique ne peut pas fonctionner et les deux éléments seront créés. Par exemple, il peut être tentant d’attribuer un identifiant à background ou à contentItem afin que d’autres objets du fichier puissent faire référence à ces éléments :
T.Button {
// ...
background: Rectangle {
id: backgroundRect
// ...
}
contentItem: Text {
// Use backgroundRect in some way...
}
// ...
}Avec ce code, chaque fois qu’une instance de Button avec un arrière-plan personnalisé est créée, les deux arrière-plans seront créés, ce qui se traduira par des performances de création sous-optimales.
Avant Qt 5.15, l’ancien arrière-plan inutilisé était supprimé afin de libérer les ressources qui lui étaient associées. Cependant, comme le contrôle n’est pas propriétaire de ces éléments, il ne doit pas les supprimer. À partir de Qt 5.15, les anciens éléments ne sont plus supprimés ; l’élément ` backgroundRect ` subsiste donc plus longtemps que nécessaire — généralement jusqu’à la fermeture de l’application. Bien que l’ancien élément soit masqué, visuellement dissocié du contrôle et supprimé de l’arborescence d’accessibilité, il est important de garder à l’esprit le temps de création et l’utilisation de mémoire de ces éléments inutilisés lors de l’attribution d’un identifiant dans ce contexte.
Évitez les affectations impératives d’éléments personnalisés
La technique mentionnée dans la section ci-dessus ne fonctionne que lorsqu’un élément est attribué de manière déclarative pour la première fois ; les attributions impératives entraîneront donc la création d’éléments orphelins. Utilisez toujours des liaisons déclaratives pour attribuer des éléments personnalisés lorsque cela est possible.
N'importez pas QtQuick.Controls dans les implémentations QML
Lorsque vous écrivez le code QML pour l'implémentation d'un contrôle dans votre style, il est important de ne pas importer QtQuick.Controls. Cela empêcherait le code QML d'être compilé par le compilateur QML.
Implémentez les types utilisés par d'autres types
Supposons que vous utilisiez des ScrollViews dans votre application et que vous décidiez de personnaliser leurs barres de défilement. Il serait tentant de simplement implémenter un fichier personnalisé ScrollBar.qml et de laisser ScrollView récupérer automatiquement le fichier ScrollBar personnalisé. Cependant, cela ne fonctionnera pas. Vous devez implémenter à la fois ScrollBar.qml et ScrollView.qml.
Propriétés associées
Il est courant qu’un style dispose de certaines propriétés ou d’attributs qui s’appliquent à tous les contrôles. Les propriétés associées constituent un excellent moyen d’étendre un élément en QML sans avoir à modifier le code C++ existant associé à cet élément. Par exemple, les styles « Material » et « Universal » disposent tous deux d’une propriété « theme » associée qui détermine si un élément et ses enfants seront affichés avec un thème clair ou sombre.
À titre d’exemple, ajoutons une propriété attachée qui contrôle l’élévation. Notre style illustrera l’élévation à l’aide d’une ombre portée ; plus l’élévation est élevée, plus l’ombre est grande.
La première étape consiste à créer une nouvelle application « Qt Quick Controls » sur Qt Creator ou sur Qt Extension for Visual Studio Code. Ensuite, nous ajoutons un type C++ (sur Qt Creator ou sur Qt Extension for Visual Studio Code) qui stocke l’élévation. Étant donné que ce type sera utilisé pour tous les contrôles pris en charge par notre style, et que nous pourrions souhaiter ajouter d’autres propriétés attachées ultérieurement, nous l’appellerons «MyStyle». Voici le fichier « 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_HMyStyle.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();
}Le type ` MyStyle ` est particulier dans la mesure où il ne doit pas être instancié, mais plutôt utilisé pour ses propriétés associées. C'est pourquoi nous l'enregistrons de la manière suivante dans ` 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();
}Nous copions ensuite ` Button.qml ` depuis le style « Basic » situé dans ` $QTDIR/qml/QtQuick/Controls/Basic/ ` vers un nouveau dossier ` myproject ` dans le répertoire de notre projet. Ajoutez le fichier ` Button.qml ` ainsi copié à ` qml.qrc`, qui est le fichier de ressources contenant nos fichiers QML.
Ensuite, nous ajoutons une ombre portée au délégué ` background ` du bouton :
// ...
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
}
}Notez que nous :
- N'utilisons pas l'ombre portée lorsque l'élévation est
0 - Modifions la couleur de l'ombre selon que le bouton a ou non le focus
- Faisons en sorte que la taille de l'ombre dépende de l'élévation
Pour tester cette propriété associée, nous créons une classe « Row » contenant deux boutons dans « 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
}
}
}L'un des boutons n'a pas de relief, tandis que l'autre présente un relief de 10.
Une fois cela en place, nous pouvons exécuter notre exemple. Pour indiquer à l’application d’utiliser notre nouveau style, nous passons -style MyStyle en tant qu’argument d’application, mais il existe de nombreuses façons de spécifier le style à utiliser.
Résultat final :

Notez que l'instruction import MyStyle 1.0 n'est nécessaire que parce que nous utilisons la propriété attachée appartenant à MyStyle. Les deux boutons utiliseront notre style personnalisé, même si nous supprimions l'importation.
Référence de personnalisation
Les extraits de code suivants présentent des exemples dans lesquels les contrôles du style « Basic » ont été personnalisés en utilisant la même approche que celle décrite dans la section « Personnalisation d’un contrôle ». Ce code peut servir de point de départ pour mettre en œuvre une apparence personnalisée.
Remarque : les styles macOS et Windows ne se prêtent pas à la personnalisation. Il est plutôt recommandé de toujours baser un contrôle personnalisé sur un style unique disponible sur toutes les plateformes, par exemple le style « Basic », « Fusion », « Imagine », « Material » ou « Universal ». Vous aurez ainsi la garantie que l’apparence restera toujours la même, quel que soit le style utilisé pour exécuter l’application. Pour savoir comment utiliser un style différent, consultez la section « Utilisation des styles » dans Qt Quick Controls. Vous pouvez également créer votre propre style.
Remarque : lorsque vous modifiez la taille des contrôles, la taille réelle du contenu reste généralement inchangée. Par exemple, certains styles peuvent faire en sorte que leur bouton occupe toute la surface du contrôle, tout en centrant horizontalement et/ou verticalement l’indicateur de sélection et le texte d’un CheckBox. Si le comportement par défaut en matière de redimensionnement ne vous convient pas, redéfinissez le ou les délégués concernés.
Personnalisation de ApplicationWindow
ApplicationWindow se compose d’un seul élément visuel : background.
import QtQuick
import QtQuick.Controls.Basic
ApplicationWindow {
visible: true
background: Rectangle {
gradient: Gradient {
GradientStop { position: 0; color: "#ffffff" }
GradientStop { position: 1; color: "#c1bbf9" }
}
}
}Personnalisation de BusyIndicator
BusyIndicator se compose de deux éléments visuels : background et 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
}
]
}
}
}
}
}Personnalisation du bouton
Le bouton se compose de deux éléments visuels : background et contentItem.

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
}
}Personnalisation de la case à cocher
CheckBox se compose de trois éléments visuels : background, contentItem et 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 {
largeur: 14
hauteur: 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
}
}Personnalisation de CheckDelegate
CheckDelegate se compose de trois éléments visuels : background, contentItem et 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"
}
}Personnalisation de ComboBox
ComboBox se compose de background, contentItem, popup, indicator et 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
}
}
}Comme expliqué dans ComboBox Model Roles, ComboBox prend en charge plusieurs types de modèles.
Étant donné que tous les modèles fournissent une propriété anonyme avec modelData, l'expression suivante permet d'extraire le texte approprié dans tous les cas :
text: model[control.textRole]Lorsque vous fournissez un textRole spécifique et un modèle contenant des données structurées qui fournissent le rôle sélectionné, cette expression correspond à une recherche de propriété classique. Lorsque vous fournissez un modèle contenant des données au singulier, telles qu’une liste de chaînes de caractères, et un textRole vide, cette expression récupère l’ modelData.
Personnalisation de DelayButton
DelayButton se compose de deux éléments visuels : background et contentItem.

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()
}
}
}
}Personnalisation de Dial
Le cadran se compose de deux éléments visuels : background et handle.

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
}
]
}
}Personnalisation de la DoubleSpinBox
DoubleSpinBox peut être personnalisé de la même manière que le bouton.
Personnalisation de Drawer
Le tiroir peut comporter un élément d'background.
background: Rectangle {
Rectangle {
x: parent.width - 1
width: 1
height: parent.height
color: "#21be2b"
}
}Personnalisation du cadre
Le cadre se compose d'un élément visuel : « background ».

import QtQuick
import QtQuick.Controls.Basic
Frame {
background: Rectangle {
color: "transparent"
border.color: "#21be2b"
radius: 2
}
Label {
text: qsTr("Content goes here!")
}
}Personnalisation de GroupBox
GroupBox se compose de deux éléments visuels : background et 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!")
}
}Personnalisation de ItemDelegate
ItemDelegate comprend deux éléments visuels : background et contentItem.

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
}
}
}Personnalisation de Label
Label peut disposer d'un élément visuel de type « background ».

import QtQuick
import QtQuick.Controls.Basic
Label {
text: qsTr("Label")
color: "#21be2b"
}Personnalisation du menu
- Menu comprend un élément visuel « background ».
- MenuItem Se compose de quatre éléments visuels : background, contentItem, indicator et arrow.
- MenuSeparator se compose d’un élément visuel « background » et d’un élément « contentItem ».

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
}
}Personnalisation de MenuBar
MenuBar peut comporter un élément d’ background, et MenuBarItem se compose de deux éléments d’ : background et contentItem.

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
}
}
}Personnalisation de PageIndicator
PageIndicator comprend un « background », un « contentItem » et un « 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
}
}
}
}Personnalisation du volet
Le volet se compose d’un élément background.

import QtQuick
import QtQuick.Controls.Basic
Pane {
background: Rectangle {
color: "#eeeeee"
}
Label {
text: qsTr("Content goes here!")
}
}Personnalisation de la fenêtre contextuelle
La fenêtre contextuelle se compose d’un élément « background » et d’un élément « contentItem ».

import QtQuick
import QtQuick.Controls.Basic
Popup {
id: popup
background: Rectangle {
implicitWidth: 200
implicitHeight: 200
border.color: "#444"
}
contentItem: Column {}
}Personnalisation de la barre de progression
ProgressBar Elle se compose de deux éléments visuels : un « background » et un « contentItem ».

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
}
}
}
}
}Ci-dessus, le « contentItem » est également animé pour représenter l'état d'une barre de progression « indeterminate ».
Personnalisation de RadioButton
RadioButton comprend trois éléments visuels : background, contentItem et 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
}
}Personnalisation de RadioDelegate
RadioDelegate comprend trois éléments visuels : background, contentItem et 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"
}
}Personnalisation de RangeSlider
RangeSlider comprend trois éléments visuels : background, first.handle et 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"
}
}La personnalisation de RoundButton
RoundButton peut être personnalisé de la même manière que Button.
Personnalisation de ScrollBar
ScrollBar comprend deux éléments visuels : background et contentItem.

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 {}
}
}
}Personnalisation de ScrollIndicator
ScrollIndicator comprend deux éléments visuels : background et contentItem.

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"
}
}La personnalisation de ScrollView
ScrollView comprend un élément « background », ainsi que des barres de défilement horizontales et verticales.

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"
}
}Personnalisation de Slider
Le Slider se compose de deux éléments visuels : background et 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"
}
}Personnalisation de la SpinBox
SpinBox se compose de quatre éléments visuels : background, contentItem, up indicator et 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"
}
}La personnalisation de SplitView
SplitView consiste en un délégué visuel handle.

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"
}
}La personnalisation de StackView
StackView peut comporter un élément d’ background visuelle et permet de personnaliser les transitions utilisées pour les opérations « push », « pop » et « replace ».
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
}
}
}Personnalisation de SwipeDelegate
SwipeDelegate comprend six éléments visuels : background, contentItem, indicator, swipe.left, swipe.right et 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
}
}
}
}Personnalisation de SwipeView
SwipeView peut comporter un élément d'background. La navigation est mise en œuvre par contentItem.
import QtQuick
import QtQuick.Controls.Basic
SwipeView {
id: control
background: Rectangle {
color: "#eeeeee"
}
}Personnalisation de Switch
Switch se compose de trois éléments visuels : background, contentItem et 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
}
}Personnalisation de SwitchDelegate
SwitchDelegate se compose de trois éléments visuels : background, contentItem et 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"
}
}Personnalisation de TabBar
TabBar comprend deux éléments visuels : background et 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")
}
}La personnalisation de TabButton
TabButton peut être personnalisé de la même manière que Button.
Personnalisation de TextArea
TextArea Elle se compose d'un élément « 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"
}
}Personnalisation de TextField
TextField consiste en un élément « background ».

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"
}
}Personnalisation de la barre d'outils
ToolBar comprend un élément visuel : 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")
}
}
}Personnalisation de ToolButton
ToolButton comprend deux éléments visuels : « background » et « contentItem ».

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))
}
}Personnalisation de ToolSeparator
ToolSeparator comprend deux éléments visuels : background et contentItem.

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
}
}
}Personnalisation de ToolTip
ToolTip comprend deux éléments visuels : background et 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"
}
}Remarque : pour personnaliser l’ attached ToolTip, celui-ci doit être fourni dans le cadre de votre propre style. Pour effectuer une personnalisation ponctuelle d’un ToolTip, consultez Custom Tool Tips.
Personnalisation de Tumbler
Tumbler se compose de trois éléments visuels : background, contentItem et 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"
}
}Si vous souhaitez définir votre propre `contentItem`, utilisez soit un ` ListView `, soit un ` PathView ` comme élément racine. Pour un Tumbler avec retour à la ligne, utilisez ` 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
}
}Pour un Tumbler sans mise en page, utilisez 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
}
}Personnalisation de TableViewDelegate
TableViewDelegate hérite de ItemDelegate, ce qui signifie qu’il est composé de deux éléments visuels : background et contentItem.
Vous pouvez à tout moment attribuer votre propre délégué d'édition personnalisé à ` editDelegate ` si vos besoins vont au-delà de ce qu'offre le délégué d'édition par défaut.

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
}
}
}Personnalisation de HeaderViewDelegate
HeaderViewDelegate hérite de TableViewDelegate, ce qui signifie qu’il est composé de deux éléments : background et contentItem. Vous pouvez à tout moment les personnaliser avec n’importe quel élément de votre choix.

Voici un exemple de personnalisation du délégué de vue d'en-tête horizontal :
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
}
}
}Voici un exemple de personnalisation du délégué de vue d’en-tête vertical :
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
}
}
}Personnalisation des contrôles à l’aide de StyleKit
Le module StyleKit de Qt Labs fournit un ensemble de types QML permettant de styliser Qt Quick Controls, s’appuyant sur Qt Quick Templates 2. Il vous permet de définir un style visuel complet pour tous vos contrôles à partir d’un seul objet Style, y compris la prise en charge des thèmes, du stylisme basé sur les états et des transitions. StyleKit gère automatiquement l’implémentation sous-jacente des modèles, ce qui vous permet de vous concentrer exclusivement sur les aspects visuels tels que les couleurs, les dimensions, les bordures et les ombres.
Le module StyleKit de Qt Labs est un module « Technology Preview » dans 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.