Comment un style dessine un widget
L'API d'QStyle propose trois types de fonctions : des fonctions qui dessinent les widgets, des aides statiques pour les tâches courantes et complexes telles que le calcul de la position d'une poignée de curseur, et des fonctions permettant d'effectuer les calculs dont les widgets ont besoin lors du dessin, par exemple pour déterminer leurs indications de taille. Le style aide également certains widgets à organiser leur contenu et peut ajuster l’ QPalette e avec laquelle les widgets s’affichent.
Cette page décrit les éléments constitutifs sur lesquels repose la mise en œuvre d’un style. La référence des styles de widgets répertorie ceux que chaque widget utilise.
Éléments de style
QStyle dessinent des éléments graphiques. Un élément est un widget ou une partie de widget, comme le biseau d’un bouton-poussoir, le cadre d’une fenêtre ou une barre de défilement. La plupart des fonctions de dessin prennent quatre arguments :
- Une valeur d’énumération qui spécifie l’élément graphique à dessiner.
- Un « QStyleOption » qui précise comment et où afficher cet élément.
- Un « QPainter » à utiliser pour dessiner l’élément.
- L’ QWidget sur lequel le dessin est effectué. Cet argument est facultatif.
Lorsqu’un widget demande à un style de dessiner un élément, il lui fournit un « QStyleOption », une classe contenant les informations nécessaires au dessin. Comme cette option contient tout ce dont le style a besoin, celui-ci peut dessiner des widgets sans avoir à se lier à aucun code de widget. Vous pouvez dessiner une liste déroulante sur n’importe quel périphérique de dessin, et pas seulement sur un « QComboBox ».
Le widget est transmis en tant que dernier argument au cas où le style en aurait besoin pour des effets spéciaux, tels que les boutons par défaut animés sous macOS, mais le style ne peut pas compter dessus. Les widgets qui dessinent eux-mêmes plusieurs éléments se transmettent eux-mêmes, tout comme ` QStylePainter`. Le code qui dessine directement sur un périphérique de dessin peut transmettre ` nullptr`.
Un widget est constitué d’une hiérarchie, ou d’une arborescence, d’éléments de style. Par exemple, lorsqu’un style reçoit une requête pour dessiner un bouton-poussoir, il dessine une étiquette (texte et icône), un biseau de bouton et un cadre de focus. Le biseau du bouton se compose lui-même d’un cadre entourant le biseau et le panneau. L’arborescence conceptuelle suivante présente les éléments du bouton-poussoir dans l’ordre de dessin, les éléments imbriqués étant dessinés par l’élément qui leur est supérieur :
- Bouton
- Biseau du bouton
- Cadre de bouton par défaut
- Panneau du bouton
- Étiquette (icône et texte)
- Cadre de mise au point
- Biseau du bouton
Les boutons de la référence affichent l'arborescence réelle de QPushButton, avec les noms des éléments.
Les widgets ne demandent pas nécessairement au style de ne dessiner qu’un seul élément. Un widget peut effectuer plusieurs appels au style pour dessiner différents éléments. C’est le cas, par exemple, de QTabWidget, qui dessine ses onglets et son cadre individuellement.
Il existe trois types d’éléments : les éléments primitifs, les éléments de contrôle et les éléments de contrôle complexes. Les énumérations PrimitiveElement, ControlElement et ComplexControl les définissent. Les valeurs de chaque énumération sont précédées d’un préfixe identifiant leur type : PE_ pour les éléments primitifs, CE_ pour les éléments de contrôle et CC_ pour les éléments de contrôle complexes. La documentation de la classe QStyle répertorie ces éléments et leurs rôles dans la mise en forme des widgets.
Éléments primitifs
Les éléments primitifs sont des éléments d’interface graphique courants, souvent utilisés par plusieurs widgets. Il s’agit par exemple des cadres, des biseaux de boutons et des flèches des champs de sélection, des barres de défilement et des listes déroulantes. Les éléments primitifs ne peuvent pas exister seuls ; ils font toujours partie d’une structure plus large. Ils ne participent pas à l’interaction avec l’utilisateur, mais constituent des éléments décoratifs passifs de l’interface graphique.
Éléments de contrôle
Un élément de contrôle effectue une action ou affiche des informations à l’utilisateur. Les boutons poussoirs, les cases à cocher et les en-têtes dans les tableaux et les arborescences sont des exemples d’éléments de contrôle. Un élément de contrôle n’est pas toujours un widget complet, tel qu’un bouton ; il peut également s’agir d’une partie de widget, comme un onglet d’une barre d’onglets ou un curseur de barre de défilement. Les éléments de contrôle se distinguent des éléments primitifs en ce qu’ils ne sont pas passifs : ils participent à l’interaction avec l’utilisateur.
Les contrôles composés de plusieurs éléments utilisent souvent le style pour calculer les rectangles englobants de ces éléments. L’énumération SubElement définit les sous-éléments disponibles. Cette énumération sert uniquement à calculer les rectangles englobants. Les sous-éléments ne sont pas des éléments graphiques à dessiner, contrairement aux éléments primitifs, aux contrôles et aux éléments complexes.
Éléments de contrôle complexes
Les éléments de contrôle complexes contiennent des sous-contrôles. Les contrôles complexes se comportent différemment selon l’endroit où l’utilisateur les manipule avec la souris et selon les touches du clavier qui sont enfoncées. Cela dépend du sous-contrôle, le cas échéant, sur lequel la souris est positionnée ou sur lequel une touche est enfoncée. Les barres de défilement et les listes déroulantes sont des exemples de contrôles complexes. Avec une barre de défilement, vous pouvez utiliser la souris pour déplacer le curseur et appuyer sur les boutons « ligne vers le haut » et « ligne vers le bas ». L'énumération « SubControl » définit les sous-contrôles disponibles.
Outre le dessin, le style indique aux widgets sur quel sous-contrôle, le cas échéant, l’utilisateur a cliqué. Par exemple, un QScrollBar doit savoir si l’utilisateur a cliqué sur le curseur, sur la rainure du curseur ou sur l’un des boutons.
Les sous-contrôles ne sont pas identiques aux éléments de contrôle. Vous ne pouvez pas utiliser le style pour dessiner un sous-contrôle ; le style calcule uniquement le rectangle de délimitation dans lequel le sous-contrôle doit être dessiné. Il est toutefois courant que des éléments complexes utilisent des éléments de contrôle et des éléments primitifs pour dessiner leurs sous-contrôles. Les styles intégrés de Qt procèdent souvent ainsi. Par exemple, QCommonStyle utilise PE_IndicatorCheckBox pour dessiner la case à cocher dans les zones de groupe, qui est un sous-contrôle de CC_GroupBox. Certains sous-contrôles ont un élément de contrôle équivalent, par exemple le curseur de la barre de défilement (SC_ScrollBarSlider et CE_ScrollBarSlider).
Sous-éléments, sous-contrôles et mesures en pixels
Les éléments de style et les widgets utilisent le style pour calculer les rectangles de délimitation des sous-éléments et des sous-contrôles. Les métriques en pixels, qui sont des tailles exprimées en pixels d’écran et dépendantes du style, sont également utilisées pour les mesures lors du tracé. Trois énumérations dans QStyle représentent les rectangles et les métriques en pixels disponibles : SubElement, SubControl et PixelMetric. Leurs valeurs commencent par SE_, SC_ et PM_.
Conseils de style
Le style répond également à un ensemble de conseils de style, représentés par les valeurs de l’énumération « StyleHint ». Tous les widgets n’ont pas les mêmes fonctionnalités ni la même apparence selon les différents styles. Par exemple, lorsque les éléments d’un menu ne tiennent pas dans une seule colonne à l’écran, certains styles prennent en charge le défilement tandis que d’autres affichent plusieurs colonnes pour faire tenir tous les éléments. Les widgets interrogent ces conseils à l’aide de la méthode styleHint().
Icônes standard
Un style dispose généralement d’un ensemble d’icônes standard, telles que des images d’avertissement, de question et d’erreur, destinées aux boîtes de message, aux boîtes de dialogue de fichiers et aux boutons de la barre de titre. L’énumération ` StandardPixmap ` les nomme, et la fonction ` standardIcon()` renvoie l’ QIcon correspondant à une valeur. Les widgets de Qt utilisent ces icônes ; vous devez donc les fournir lorsque vous implémentez un style.
Espacement dans les dispositions
Le style calcule l’espacement entre les widgets dans les mises en page. Il existe deux façons de gérer ces calculs. Vous pouvez récupérer l’espacement via la fonction ` pixelMetric()` pour les paramètres ` PM_LayoutHorizontalSpacing ` et ` PM_LayoutVerticalSpacing`, comme le fait la fonction ` QCommonStyle `. Vous pouvez également réimplémenter la fonction ` layoutSpacing()` si vous avez besoin d’un contrôle plus fin. Dans cette fonction, vous pouvez calculer l’espacement en fonction des types de contrôle (QSizePolicy::ControlType) des deux widgets adjacents, de leurs politiques de taille (QSizePolicy::Policy) et de l’option de style du widget concerné.
Options de style
Les sous-classes de ` QStyleOption ` contiennent toutes les informations nécessaires pour styliser les éléments individuels. L’appelant de la fonction ` QStyle ` instancie une option de style, généralement sur la pile, et la remplit. Selon ce qui est dessiné, le style attend une classe d’option de style différente. Par exemple, l’élément ` PE_FrameFocusRect ` attend un argument de type ` QStyleOptionFocusRect `. Vous pouvez également créer vos propres sous-classes pour utiliser un style personnalisé. Les options de style conservent des variables publiques pour des raisons de performances.
Les widgets peuvent se trouver dans différents états, définis par l’énumération ` State `. Certains indicateurs d’état ont des significations différentes selon le widget, mais d’autres sont communs à tous les widgets, comme ` State_Enabled`. La méthode ` QStyleOption::initFrom()` définit les états communs ; les widgets individuels définissent le reste.
Il convient notamment de noter que les options de style contiennent la palette et le rectangle de délimitation du widget à dessiner. La plupart des widgets disposent d’options de style spécialisées. QPushButton et QCheckBox, par exemple, utilisent QStyleOptionButton, qui contient le texte, l’icône et la taille de celle-ci. La section « Référence des styles de widgets » décrit le contenu exact de chaque option.
Lorsque vous réimplémentez des fonctions de ` QStyle ` qui prennent un paramètre ` QStyleOption `, vous devez souvent convertir l’option en une sous-classe, telle que ` QStyleOptionFocusRect`. Utilisez ` qstyleoption_cast()` pour vous assurer que le type du pointeur est correct. Si l’objet n’est pas du bon type, ` qstyleoption_cast()` renvoie ` nullptr` :
const QStyleOptionFocusRect *focusRectOption =
qstyleoption_cast<const QStyleOptionFocusRect *>(option);
if (focusRectOption) {
//...
}Indicateurs d’état et membres communs
Certains états et variables sont communs à tous les widgets. Les widgets les définissent à l’aide de la fonction QStyleOption::initFrom(). Tous les éléments n’utilisent pas cette fonction. Les widgets créent les options de style, et pour certains éléments, les informations fournies par la fonction initFrom() ne sont pas nécessaires.
| État | Définie lorsque |
|---|---|
State_Enabled | Le widget n’est pas désactivé (voir QWidget::isEnabled()). |
State_HasFocus | Le widget a le focus (voir QWidget::hasFocus()). |
State_KeyboardFocusChange | L'utilisateur a changé de focus à l'aide du clavier (voir WA_KeyboardFocusChange). |
State_MouseOver | Le curseur de la souris se trouve sur le widget. |
State_Active | Le widget est un enfant de la fenêtre active. |
Les autres membres courants sont :
| Membre | Description |
|---|---|
| rect | Le rectangle de délimitation de l'élément à dessiner. La méthode ` initFrom() ` le définit comme étant le rectangle de délimitation du widget (QWidget::rect()). |
| direction | La direction de mise en page, une valeur de l'énumération Qt::LayoutDirection. |
| palette | La palette de couleurs « QPalette » à utiliser lors du dessin de l’élément. La fonction ` initFrom() ` la définit sur la palette du widget (`QWidget::palette()`). |
| fontMetrics | L’ QFontMetrics à utiliser lors du dessin du texte sur le widget. |
| styleObject | L’objet décrit par l’option, généralement le widget. Les styles l’utilisent pour stocker l’état d’animation. |
Les options de style complexes (classes héritant de ` QStyleOptionComplex`) partagent deux variables supplémentaires : ` subControls ` et ` activeSubControls`. Toutes deux sont des combinaisons « OU » de valeurs de ` QStyle::SubControl `. Elles indiquent de quels sous-contrôles se compose le contrôle complexe et lesquels d’entre eux sont actuellement actifs.
Fonctions QStyle
QStyle définit trois fonctions pour dessiner les éléments primitifs, les contrôles et les éléments complexes : drawPrimitive(), drawControl() et drawComplexControl(). Elles prennent les arguments répertoriés dans la section Éléments de style.
Tous les widgets ne transmettent pas un pointeur vers eux-mêmes. Si l’option de style transmise à la fonction ne contient pas les informations dont vous avez besoin, vérifiez l’implémentation du widget pour voir s’il se transmet lui-même.
QStyle fournit également des fonctions d’aide pour le dessin d’éléments. drawItemText() dessine du texte à l’intérieur d’un rectangle spécifié, en prenant un QPalette comme paramètre. drawItemPixmap() aligne une image pixel (pixmap) à l’intérieur d’un rectangle de délimitation spécifié.
D’autres fonctions ` QStyle ` effectuent des calculs pour les fonctions de dessin. Les widgets les utilisent également pour calculer les indications de taille et les rectangles de délimitation lorsqu’ils dessinent eux-mêmes plusieurs éléments de style. Ces fonctions prennent généralement les mêmes arguments que les fonctions de dessin.
- subElementRect() prend une valeur d’ SubElement et calcule le rectangle de délimitation d’un sous-élément. Le style utilise cette fonction pour savoir où dessiner les différentes parties d’un élément. Si vous créez un nouveau style, vous pouvez réutiliser les positions des sous-éléments de la classe de base.
- subControlRect() calcule les rectangles englobants des sous-contrôles dans les contrôles complexes. Lorsque vous implémentez un nouveau style, réimplémentez-la pour les rectangles qui diffèrent de ceux de la classe de base.
- pixelMetric() renvoie une métrique en pixels, une taille dépendante du style exprimée en pixels d’écran. Elle prend une valeur de l’énumération PixelMetric. Les métriques en pixels ne sont pas nécessairement des mesures statiques ; vous pouvez les calculer à partir de l’option de style.
- sizeFromContents() renvoie la taille d’un widget pour une taille de contenu donnée. Les widgets l’utilisent pour calculer leurs indications de taille.
- hitTestComplexControl() renvoie le sous-contrôle sur lequel se trouve le pointeur de la souris dans un contrôle complexe. En général, il suffit d’utiliser subControlRect() pour obtenir les rectangles de délimitation des sous-contrôles et de trouver celui qui contient la position du curseur.
QStyle dispose également des fonctions polish() et unpolish(). Qt applique un « polissage » à chaque widget avant son premier affichage, puis à nouveau lorsque le style change, et annule ce « polissage » lorsque le style change ou que le widget est détruit. Utilisez ces fonctions pour définir des attributs sur les widgets ou pour effectuer d’autres tâches requises par votre style. Par exemple, si vous avez besoin de savoir quand la souris survole un widget, définissez l’attribut de widget ` WA_Hover ` dans ` polish()`. Le widget définit alors ` State_MouseOver ` dans ses options de style. Les surcharges de ` polish() ` permettent également au style de préparer l’ QApplication et d’ajuster la palette de l’application ; voir La palette.
Enfin, la classe ` QStyle ` dispose de fonctions d’aide statiques pour les tâches courantes et complexes. Les méthodes ` sliderPositionFromValue()` et ` sliderValueFromPosition()` assurent la conversion entre les valeurs du curseur et les positions en pixels. Les méthodes ` visualRect()`, ` visualPos()` et ` visualAlignment()` convertissent les coordonnées et les alignements logiques en leurs équivalents inversés dans les mises en page de droite à gauche, tandis que la méthode ` alignedRect()` aligne un rectangle selon la direction actuelle. Pour plus de détails, consultez la section « Right-to-Left Desktops » dans la documentation de la classe ` QStyle `.
Lorsque vous réimplémentez les fonctions virtuelles de ` QStyle `, gérez les éléments qui diffèrent de la classe de base et appelez l’implémentation de la classe de base pour tout le reste.
La palette
Chaque style utilise une palette de pinceaux fournie par QPalette. Il existe un jeu de couleurs, un QPalette::ColorGroup, pour chaque état de widget : « actif » pour les widgets de la fenêtre qui a le focus clavier, « inactif » pour les widgets des autres fenêtres et « désactivé » pour les widgets désactivés. Les indicateurs d’état State_Active et State_Enabled vous indiquent quel groupe utiliser. Chaque groupe contient les rôles de couleur définis par QPalette::ColorRole. Ces rôles décrivent les situations auxquelles les couleurs sont destinées, telles que la coloration de l’arrière-plan des widgets, du texte ou des boutons.
Chaque style détermine comment utiliser ces rôles de couleur. Par exemple, si le style utilise des dégradés, il peut prendre une couleur de la palette et l’assombrir ou l’éclaircir à l’aide de QColor::darker() et QColor::lighter() pour créer le dégradé. En général, si vous avez besoin d’un pinceau que la palette ne fournit pas, dérivez-le d’un pinceau existant.
Lorsque vous définissez un style sur l’application, Qt construit la palette de l’application à partir de la fonction ` standardPalette()` du style, laisse le thème de la plateforme remplacer les rôles qu’il fournit, puis transmet le résultat à ` QStyle::polish()`. Réimplémentez cette surcharge pour ajuster les couleurs dont votre style a besoin. Qt ne remplace pas une palette que l’application a définie explicitement avec ` QApplication::setPalette()`.
Ne codez pas les couleurs en dur. Les applications et les widgets individuels peuvent définir leur propre palette, et un style qui utilise cette palette s’y conforme. Il obtient également une variante claire et une variante sombre à partir de deux palettes, sans aucun code supplémentaire. Le style Fusion de Qt fonctionne de cette manière :
|
|
Un style n’a pas besoin d’être esthétique avec toutes les palettes imaginables, mais il doit respecter la palette qui lui est fournie.
Vues d’éléments
Les délégués dessinent les éléments dans les vues d’éléments. Le délégué par défaut de Qt, ` QStyledItemDelegate`, dessine les éléments à l’aide de ` CE_ItemViewItem ` et calcule leur taille avec ` CT_ItemViewItem` ; un style contrôle donc l’apparence des éléments sans délégat associé. Le style dessine directement les en-têtes des vues d’éléments, les indicateurs de branches d’arborescence et les arrière-plans des lignes. Pour prendre en charge de nouveaux types de données ou de nouveaux rôles de données d’éléments, vous avez besoin d’un délégué personnalisé ; voir Programmation modèle/vue.
Conseils de mise en œuvre
Lorsque vous implémentez un style, lisez le code des widgets et de la classe de base. Les widgets utilisent le style de différentes manières, et l’implémentation de la classe de base peut affecter l’état du tracé, par exemple en modifiant l’état de QPainter sans le restaurer, ou en dessinant certains éléments sans utiliser les métriques de pixels et les sous-éléments appropriés.
Ne modifiez pas la taille proposée des widgets dans ` sizeFromContents()` sauf si vous y êtes contraint ; laissez l’implémentation de ` QCommonStyle ` s’en charger. Si vous apportez des modifications, veillez à ce qu’elles soient minimes. Le développement d’applications s’avère difficile lorsque la disposition des widgets diffère considérablement d’un style à l’autre.
Testez votre style à l’aide de l’option de ligne de commande -reverse ou de la fonction QGuiApplication::setLayoutDirection(), afin de vous assurer que les éléments asymétriques s’affichent correctement dans une mise en page de droite à gauche.
Voir également QStyle, QStyleOption, QStylePainter, Référence sur les styles de widgets et Mise en forme d’une case à cocher : guide pratique.
© 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.

