I. L'article original▲
Qt Quarterly est une revue trimestrielle électronique proposée par Nokia à destination des développeurs et utilisateurs de Qt. Vous pouvez trouver les versions originales.
Nokia, Qt, Qt Quarterly et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.
Cet article est la traduction de l'article Custom Looks using Qt 4.2 Style Sheets paru dans la Qt Quarterly Issue 20.
Cet article est une traduction d'un des tutoriels écrits par Nokia Corporation and/or its subsidiary(-ies) inclus dans la documentation de Qt, en anglais. Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia.
II. Que sont les feuilles de style de Qt ?▲
Les feuilles de style de Qt sont fortement inspirées par les feuilles de styles HML (CSS) mais adaptées pour les widgets. Vous pouvez définir une feuille de style sur un widget enfant individuel, sur une fenêtre entière, ou même sur une application complète en appelant QWidget::setStyleSheet() ou bien QApplication::setStyleSheet().
Derrière cela, les feuilles de style sont implémentées par une sous-classe particulière de QStyle nommée QStyleSheetStyle qui agit en tant que wrapper pour le style spécifique de la plateforme. Ce modèle spécial applique à ce dernier toutes les personnalisations spécifiées par l'utilisation des feuilles de style.
Qt 4.2 inclut un exemple de feuilles de style qui vous laisse vous expérimenter avec les feuilles de style. Il vient avec deux styles : Coffee et Pagefold.
Le style Coffee montré ci-dessus personnalise le style des boutons, des cadres, des libellés et des bulles d'aide mais laisse le style à la base (par exemple, celui de Windows XP) dessiner les checkboxes, les comboboxes et les boutons radio.
En revanche, Pagefold redéfinit entièrement l'apparence de tous les contrôles utilisés dans la boîte de dialogue, ayant pour résultat distinctif une apparence indépendante à la plateforme.
Cet article se veut représenter une introduction rapide aux feuilles de style. Pour une description complète de la syntaxe des feuilles de style de Qt, veuillez vous référer à la documentation en ligne ou explorez l'exemple stylesheet, situé dans le dossier examples/widgets de Qt 4.2.
III. Syntaxe basique des feuilles de style▲
Les règles de syntaxe des feuilles de style de Qt sont la plupart du temps les mêmes que celle de CSS. Si vous connaissez déjà CSS, vous pouvez probablement passer à la partie suivante.
Une feuille de style consiste en une séquence de règles de style. Chaque règle à la forme suivante :
selector {
attribute: value }
La partie selector est typiquement un nom de classe (par exemple, QComboBox), mais d'autres syntaxes sont possibles. La partie attribute est le nom de l'attribut d'une feuille de style, et value est la valeur assignée à l'attribut.
Par commodité, nous pouvons utiliser la notation sténographique :
selector1, selector2, ..., selectorM {
attribute1
:
value1;
attribute2
:
value2;
...
attributeN
:
valueN;
}
Qui définit simultanément N attributs sur tout widget capturant n'importe lequel des M sélecteurs. Par exemple,
QCheckBox
, QComboBox
, QSpinBox
{
color
:
red;
background-
color: white;
font
:
bold;
}
Définit les couleurs de premier plan et d'arrière-plan ainsi que les polices de toutes les QCheckBox, QComboBox et QSpinBox.
La documentation en ligne liste les attributs supportés pour chaque type de widget. Dans cet article, nous allons nous concentrer sur les plus communs.
IV. Le modèle de boîte▲
Lors de l'utilisation des feuilles de style, tout widget est traité en tant que boîte avec quatre rectangles concentriques : le rectangle de marge (extérieure), le rectangle de bordure, le rectangle de marge intérieure et le rectangle de contenu. Pour un simple widget à tiret ; c'est-à-dire un widget avec 0 pixel de marge, d'épaisseur de bordure et de marge intérieure, ces quatre rectangles coïncident exactement.
La zone de marge se situe à l'extérieur de la bordure et est toujours transparente. La bordure fournit un cadre au widget. De multiples modèles intégrés de style, incluant inset, outset et ridge, sont disponibles par la définition de l'attribut border-style. La zone de marge intérieure fournit un espace entre la bordure et la zone de contenu.
V. Premiers plans et arrière-plans▲
La couleur de premier plan (la couleur utilisée pour dessiner le texte) du widget est spécifiée en utilisant l'attribut color. La couleur d'arrière-plan, spécifiée par l'utilisation de background-color, remplit le rectangle de marge intérieure du widget.
L'image d'arrière-plan, spécifiée par background-image, est dessinée dans la zone rectangulaire (rectangle de marge, de bordure, de contenu ou de marge intérieure) spécifiée par background-origin. L'alignement et la mosaïque de l'image d'arrière-plan à l'intérieur de la zone rectangulaire peuvent être modifiés respectivement à l'aide des attributs background-position et background-repeat.
Si nous spécifions une image avec chanel alpha (pour une semi-transparence), la couleur spécifiée en utilisant l'attribut background-color brillera à travers. Cela peut être utilisé pour réutiliser la même image d'arrière-plan dans des contextes différents.
L'exemple qui suit illustre l'usage des attributs que nous avons vus jusqu'ici :
QFrame
{
margin
:
10
px;
border
:
2
px solid green;
padding
:
20
px;
background-
color: gray;
background-
image: url(qt.png);
background-
position: top right;
background-
origin: content;
background-
repeat: none;
}
Dans cet exemple, les valeurs spécifiées pour la bordure, la marge et la marge intérieure s'appliquent uniformément à chacun des quatre côtés de tout QFrame présent dans l'application. L'attribut margin peut si vous le souhaitez être utilisé dans le but de spécifier des valeurs différentes pour le haut, la droite, le bas et la gauche.
QFrame
{
margin
:
14
px 18
px 20
px 18
px;
}
Alternativement, nous pouvons utiliser les attributs margin-top, margin-right, margin-bottom et margin-left :
QFrame
{
margin-
top: 14
px;
margin-
right: 18
px;
margin-
bottom: 20
px;
margin-
left: 18
px;
}
Bien que nous ayons utilisé QFrame dans les exemples ci-dessus, nous pouvons avoir spécifié tout widget de Qt supportant le model de boîte, incluant QCheckBox, QLabel, QLineEdit, QListView, QMenu, QPushButton, QTextEdit, et QToolTip.
VI. Créer des styles évolutifs▲
Par défaut, les images de fond indiquées en utilisant background-image sont répétées autant de fois que nécessaire, autant horizontalement que verticalement, afin de couvrir la zone de marges intérieures du widget (soit la zone située à l'intérieure de la bordure). Si nous voulons créer des arrière-plans qui seraient joliment mis à l'échelle des dimensions du widget, nous aurons besoin de spécifier une soi-disant "image de bordure".
Les images de bordures sont spécifiées en utilisant l'attribut border-image. Elles fournissent les bordures ainsi que l'arrière-plan du widget. Une image de bordure est découpée en neuf cellules, un petit peu comme un panneau de morpion :
Lors du remplissage de la bordure d'un widget, les quatre cellules de coin sont plus ou moins prises telles qu'elles, tandis que les cinq autres cellules sont soit étirées, soit répétées pour remplir l'espace disponible.
Lors de l'indication d'une image de bordure, nous devons spécifier les quatre "coupures" définissant les neuf cellules, en addition avec l'image de bordure elle-même. Nous devons aussi indiquer si nous voulons que les cellules n'étant pas des cellules de coin soient étirées ou répétées, et nous devons définir border-width de manière à ce que cela corresponde aux coupures (pour permettre l'évolutivité des coins).
En tant qu'exemple, voici la feuille de style nécessaire à reproduire le bouton ci-dessus (affiché sous quatre tailles différentes) :
QPushButton
{
border-
width: 4
px;
border-
image: url(button.png) 4
4
4
4
stretch stretch;
}
Comme dans le cas d'une image de fond, l'image de bordure peut détenir un chanel alpha qui se joigne avec la couleur d'arrière-plan.
VII. Contrôle des dimensions▲
Les attributs min-width et min-height peuvent être utilisés pour spécifier la longueur et la largeur minimale de la zone de contenu d'un widget. Ces valeurs affectent le minimumSizeHint() du widget en question qui sera honoré par le layout. Par exemple :
QPushButton
{
min-
width: 68
px;
min-
height: 28
px;
}
Si l'attribut n'est pas spécifié, la largeur minimale est dérivée à partir du contenu du widget ainsi que du style actuel.
VIII. Gérer les pseudo-états▲
L'apparence des widgets peut être personnalisée pour des états d'interface utilisateur spécifiques en passant par des soi-disant pseudo-états dans les feuilles de style. Par exemple, nous pouvons préférer donner à un bouton un aspect creux lorsque celui-ci serait pressé par l'utilisateur en passant par une spécification du pseudo-état :pressed :
QPushButton
{
border
:
2
px outset green;
background
:
gray;
}
QPushButton
:pressed {
border-
style: inset;
}
Voici une liste des pseudo-états disponibles :
Pseudo-état | Description |
---|---|
:checked | Le widget est coché. |
:disabled | Le bouton n'est pas activé. |
:enabled | Le bouton est activé. |
:focus | Le widget détient le fucus d'entrée. |
:hover | La souris est en train de survoler le widget. |
:indeterminate | La case à cocher ou le bouton radio est partiellement coché. |
:off | Pour les widgets pouvant être basculés, cela s'applique au widgets à l'état "off". |
:on | Pour les widgets pouvant être basculés, cela s'applique au widgets à l'état "on". Cela s'applique aussi aux comboboxes ayant leur liste ouverte, et aux barres de menus ayant l'un de leurs menus ouvert. |
:pressed | Le widget est en train d'être pressé par l'utilisation de la souris. |
:unchecked | Le bouton n'est pas coché. |
IX. Micro-personnalisation avec les sous-contrôles▲
Beaucoup de widgets contiennent des éléments embarqués, parfois appelés "sous-contrôles". Les flèches haut et bas d'une QSpinBox sont des exemples de sous-contrôle.
Les sous-contrôles peuvent être indiqués en utilisant :: (par exemple, QDateTimeEdit:: up-button). Les styliser est relativement similaire à styliser un widget. Ils suivent le model de boîte décrit plus haut (c'est-à-dire qu'ils peuvent avoir une border, un arrière-plan, etc…) et peuvent être combinés avec les pseudo-états (par exemple, QSpinBox::up-button:hover).
Le tableau ci-dessous liste les sous-contrôles disponibles aux auteurs de feuilles de style :
Sous-contrôle | Description |
---|---|
::down-arrow | La flèche vers le bas d'un QComboBox ou d'une QSpinBox. |
::down-button | Le bouton vers le bas d'une QSpinBox. |
::drop-down | Le bouton de déroulement vers le bas d'un QComboBox. |
::indicator | L'indicateur d'une QCheckBox, d'un QRadioButton ou d'une QGroupBox. |
::item | Un menu, une barre de menu ou un élément de barre d'état. |
::menu-indicator | L'indicateur de menu d'un QPushButton. |
::title | Le titre d'une QGroupBox. |
::up-arrow | La flèche vers le haut d'une QSpinBox. |
::up-button | Le bouton vers le bas d'une QSpinBox. |
Les sous-contrôles peuvent être placés n'importe où dans la boîte du widget en utilisant subcontrol-position et subcontrol-origin. Le positionnement du sous-contrôle peut être relativement bien accordé par l'utilisation du positionnement relatif ou absolu. Le choix de la technique de positionnement dépend de si le sous-contrôle détient des dimensions fixées ou détient des dimensions dépendantes de la boîte du widget.
IX-A. Positionnement relatif▲
Le positionnement relatif est approprié pour les sous-contrôles ayant une taille fixée (spécifiée en utilisant les attributs width et height). Utilisant cette technique, le sous-contrôle peut être déplacé par l'utilisation d'un décalage depuis la position qui a été définie par l'utilisation de subcontrol-position et de subcontrol-origin. L'attribut left peut être utilisé dans le but de déplacer le sous-contrôle vers la droite et l'attribut top peut lui aussi être utilisé pour déplacer le sous-contrôle vers le bas. Par exemple :
QPushButton
::
menu-
indicator {
image
:
url(menu_indicator.png);
width
:
13
px;
height
:
13
px;
subcontrol-
origin: padding;
subcontrol-
position: bottom right;
}
Quand l'utilisateur presse un bouton, nous pouvons déplacer l'indicateur de menu depuis sa position originale de quelques pixels afin de simuler un appui sur le bouton :
QPushButton
::
menu-
indicator:pressed {
position
:
relative;
top
:
2
px;
left
:
2
px;
}
IX-B. Positionnement absolu▲
Le positionnement absolu est approprié pour les sous-contrôles ayant des dimensions dépendant des dimensions de la boîte du widget. Comme précédemment, subcontrol-origin est utilisé pour définir un rectangle de référence dans la boîte du widget. La zone rectangulaire pour les sous-contrôles est alors définie en fournissant des décalages à partir des bords situés en haut, à droite, en bas et à gauche de ce rectangle de référence :
QPushButton
::
menu-
indicator {
border
:
2
px solid red;
subcontrol-
origin: padding;
position
:
absolute;
top
:
2
px;
right
:
2
px;
bottom
:
2
px;
left
:
40
px;
}
Pour les sous-contrôles ayant une longueur fixée ou bien une hauteur fixée, subcontrol-position peut être utilisé pour spécifier un alignement à l'intérieur du rectangle de subcontrol-origin :
QPushButton
::
menu-
indicator {
image
:
url(menu_indicator.png);
width
:
13
px;
subcontrol-
origin: padding;
subcontrol-
position: bottom right;
position
:
relative;
top
:
2
px;
bottom
:
2
px;
right
:
2
px;
}
X. Divers▲
Note : Cet article concerne la version 4.2 de Qt, mais les informations présentes à l'intérieur s'avèrent être toujours d'actualité.
Fidèle à ma nouvelle habitude, j'adresse ici de chaleureux remerciements à dourouc05 pour sa patience et son aide, ainsi qu'a RideKick pour sa relecture !
Au nom de toute l'équipe Qt, j'aimerais adresser le plus grand remerciement à Nokia pour nous avoir autorisé la traduction de cet article !