Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
styles-drawing.qdoc
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \page style-drawing.html
6 \title How a Style Draws a Widget
7 \brief The style elements, style options, and QStyle functions that turn a
8 widget into pixels.
9
10 The \l QStyle API has three kinds of functions: functions that draw the
11 widgets, static helpers for common and difficult tasks such as calculating
12 the position of a slider handle, and functions for the calculations that
13 widgets need while drawing, for example, to compute their size hints. The
14 style also helps some widgets lay out their contents, and it can adjust the
15 \l QPalette that the widgets draw with.
16
17 This page describes the building blocks that a style implementation works
18 with. \l{Widget Style Reference} lists which of them each widget uses.
19
20 \section1 Style elements
21
22 \l QStyle draws graphical elements. An element is a widget or a widget part,
23 such as a push button bevel, a window frame, or a scroll bar. Most drawing
24 functions take four arguments:
25
26 \list
27 \li An enum value that specifies which graphical element to draw.
28 \li A \l QStyleOption that specifies how and where to render that element.
29 \li A \l QPainter to draw the element with.
30 \li The \l QWidget that the drawing is performed on. This argument is
31 optional.
32 \endlist
33
34 When a widget asks a style to draw an element, it provides the style with a
35 \l QStyleOption, a class that contains the information necessary for
36 drawing. Because the option carries everything the style needs, the style
37 can draw widgets without linking any widget code. You can draw a combo box
38 on any paint device, not only on a \l QComboBox.
39
40 The widget is passed as the last argument in case the style needs it for
41 special effects, such as animated default buttons on \macos, but the style
42 can't rely on it. Widgets that draw several elements themselves pass
43 themselves, and so does \l QStylePainter. Code that draws directly on a
44 paint device may pass \nullptr.
45
46 A widget consists of a hierarchy, or tree, of style elements. For instance,
47 when a style receives a request to draw a push button, it draws a label
48 (text and icon), a button bevel, and a focus frame. The button bevel in turn
49 consists of a frame around the bevel and the panel. The following conceptual
50 tree shows the push button elements in drawing order, with nested elements
51 drawn by the element above them:
52
53 \list
54 \li Push button
55 \list
56 \li Button bevel
57 \list
58 \li Default button frame
59 \li Button panel
60 \endlist
61 \li Label (icon and text)
62 \li Focus frame
63 \endlist
64 \endlist
65
66 \l{Styling Buttons and Input Widgets#Push buttons}{Push buttons} in the
67 reference shows the actual tree for \l QPushButton, with the element names.
68
69 Widgets don't necessarily ask the style to draw only one element. A widget
70 can make several calls to the style to draw different elements. An example
71 is \l QTabWidget, which draws its tabs and frame individually.
72
73 There are three element types: primitive elements, control elements, and
74 complex control elements. The \l{QStyle::}{PrimitiveElement},
75 \l{QStyle::}{ControlElement}, and \l{QStyle::}{ComplexControl} enums define
76 them. The values of each enum have a prefix that identifies their type:
77 \c{PE_} for primitive elements, \c{CE_} for control elements, and \c{CC_}
78 for complex controls. The \l QStyle class documentation lists these elements
79 and their roles in styling widgets.
80
81 \section2 Primitive elements
82
83 Primitive elements are GUI elements that are common and often used by
84 several widgets. Examples are frames, button bevels, and arrows for spin
85 boxes, scroll bars, and combo boxes. Primitive elements can't exist on their
86 own; they are always part of a larger construct. They take no part in the
87 interaction with the user but are passive decorations in the GUI.
88
89 \section2 Control elements
90
91 A control element performs an action or displays information to the user.
92 Examples of control elements are push buttons, checkboxes, and header
93 sections in tables and tree views. A control element isn't always a complete
94 widget such as a push button; it can also be a widget part such as a tab bar
95 tab or a scroll bar slider. Control elements differ from primitive elements
96 in that they aren't passive: they take part in the interaction with the
97 user.
98
99 Controls that consist of several elements often use the style to calculate
100 the bounding rectangles of the elements. The \l{QStyle::}{SubElement} enum
101 defines the available subelements. This enum is only used for calculating
102 bounding rectangles. Subelements aren't graphical elements to be drawn like
103 primitive, control, and complex elements.
104
105 \section2 Complex control elements
106
107 Complex control elements contain subcontrols. Complex controls behave
108 differently depending on where the user handles them with the mouse and
109 which keyboard keys are pressed. This depends on which subcontrol, if any,
110 the mouse is over or pressed on. Examples of complex controls are scroll
111 bars and combo boxes. With a scroll bar, you can use the mouse to move the
112 slider and press the line up and line down buttons. The
113 \l{QStyle::}{SubControl} enum defines the available subcontrols.
114
115 In addition to drawing, the style tells the widgets which subcontrol, if
116 any, the user pressed. For instance, a \l QScrollBar needs to know whether
117 the user pressed the slider, the slider groove, or one of the buttons.
118
119 Subcontrols aren't the same as control elements. You can't use the style to
120 draw a subcontrol; the style only calculates the bounding rectangle in which
121 the subcontrol should be drawn. It's common, though, for complex elements to
122 use control and primitive elements to draw their subcontrols. Qt's built-in
123 styles do this frequently. For instance, \l QCommonStyle uses
124 \c PE_IndicatorCheckBox to draw the checkbox in group boxes, which is a sub
125 control of \c CC_GroupBox. Some subcontrols have an equivalent control
126 element, for example, the scroll bar slider (\c SC_ScrollBarSlider and
127 \c CE_ScrollBarSlider).
128
129 \section1 Subelements, subcontrols, and pixel metrics
130
131 The style elements and the widgets use the style to calculate the bounding
132 rectangles of subelements and subcontrols. Pixel metrics, which are
133 style-dependent sizes in screen pixels, are also used for measurements when
134 drawing. Three enums in \l QStyle represent the available rectangles and
135 pixel metrics: \l{QStyle::}{SubElement}, \l{QStyle::}{SubControl}, and
136 \l{QStyle::}{PixelMetric}. Their values start with \c{SE_}, \c{SC_}, and
137 \c{PM_}.
138
139 \section1 Style hints
140
141 The style also answers a set of style hints, represented by the values of
142 the \l{QStyle::}{StyleHint} enum. Not all widgets have the same
143 functionality and look in the different styles. For instance, when the menu
144 items in a menu don't fit in a single column on the screen, some styles
145 support scrolling while others draw more than one column to fit all items.
146 Widgets query hints with \l{QStyle::}{styleHint()}.
147
148 \section1 Standard icons
149
150 A style usually has a set of standard icons, such as warning, question, and
151 error images, for message boxes, file dialogs, and title bar buttons. The
152 \l{QStyle::}{StandardPixmap} enum names them, and
153 \l{QStyle::}{standardIcon()} returns the \l QIcon for a value. Qt's widgets
154 use these icons, so when you implement a style, supply them.
155
156 \section1 Layout spacing
157
158 The style calculates the spacing between widgets in layouts. There are two
159 ways to handle these calculations. You can return the spacing from
160 \l{QStyle::}{pixelMetric()} for \c PM_LayoutHorizontalSpacing and
161 \c PM_LayoutVerticalSpacing, which \l QCommonStyle does. Alternatively, you
162 can reimplement \l{QStyle::}{layoutSpacing()} if you need more control. In
163 that function, you can calculate the spacing based on the control types
164 (\l{QSizePolicy::ControlType}) of the two adjacent widgets, their size
165 policies (\l{QSizePolicy::Policy}), and the style option for the widget in
166 question.
167
168 \section1 Style options
169
170 The subclasses of \l QStyleOption contain all information necessary to style
171 the individual elements. The caller of the \l QStyle function instantiates a
172 style option, usually on the stack, and fills it out. Depending on what is
173 drawn, the style expects a different style option class. For example, the
174 \c PE_FrameFocusRect element expects a \l QStyleOptionFocusRect argument.
175 You can also create your own subclasses for a custom style to use. The style
176 options keep public variables for performance reasons.
177
178 Widgets can be in a number of different states, defined by the
179 \l{QStyle::}{State} enum. Some of the state flags have different meanings
180 depending on the widget, but others are common for all widgets, such as
181 \c State_Enabled. \l QStyleOption::initFrom() sets the common states; the
182 individual widgets set the rest.
183
184 Most notably, the style options contain the palette and bounding rectangle
185 of the widget to be drawn. Most widgets have specialized style options.
186 \l QPushButton and \l QCheckBox, for instance, use \l QStyleOptionButton,
187 which contains the text, the icon, and the size of the icon.
188 \l{Widget Style Reference} describes the exact contents of each option.
189
190 When you reimplement \l QStyle functions that take a \l QStyleOption
191 parameter, you often need to cast the option to a subclass, such as
192 \l QStyleOptionFocusRect. Use qstyleoption_cast() to ensure that the pointer
193 type is correct. If the object isn't of the right type, qstyleoption_cast()
194 returns \nullptr:
195
196 \snippet code/doc_src_qt4-styles.cpp 0
197
198 \section2 Common state flags and members
199
200 Some states and variables are common for all widgets. Widgets set them with
201 \l QStyleOption::initFrom(). Not all elements use this function. The widgets
202 create the style options, and for some elements the information from
203 \l{QStyleOption::}{initFrom()} isn't necessary.
204
205 \table 90%
206 \header
207 \li State
208 \li Set when
209 \row
210 \li \c State_Enabled
211 \li The widget isn't disabled (see \l{QWidget::isEnabled()}).
212 \row
213 \li \c State_HasFocus
214 \li The widget has focus (see \l{QWidget::hasFocus()}).
215 \row
216 \li \c State_KeyboardFocusChange
217 \li The user changed focus with the keyboard (see
218 \l{Qt::}{WA_KeyboardFocusChange}).
219 \row
220 \li \c State_MouseOver
221 \li The mouse cursor is over the widget.
222 \row
223 \li \c State_Active
224 \li The widget is a child of the active window.
225 \endtable
226
227 The other common members are:
228
229 \table 90%
230 \header
231 \li Member
232 \li Description
233 \row
234 \li \l{QStyleOption::}{rect}
235 \li The bounding rectangle of the element to draw. \c initFrom()
236 sets it to the widget's bounding rectangle
237 (\l{QWidget::rect()}).
238 \row
239 \li \l{QStyleOption::}{direction}
240 \li The layout direction, a value of the \l{Qt::LayoutDirection}
241 enum.
242 \row
243 \li \l{QStyleOption::}{palette}
244 \li The \l QPalette to use when drawing the element. \c initFrom()
245 sets it to the widget's palette (\l{QWidget::palette()}).
246 \row
247 \li \l{QStyleOption::}{fontMetrics}
248 \li The \l QFontMetrics to use when drawing text on the widget.
249 \row
250 \li \l{QStyleOption::}{styleObject}
251 \li The object that the option describes, usually the widget. Styles
252 use it to store animation state.
253 \endtable
254
255 The complex style options (classes that inherit \l{QStyleOptionComplex})
256 share two more variables: \l{QStyleOptionComplex::}{subControls} and
257 \l{QStyleOptionComplex::}{activeSubControls}. Both are OR combinations of
258 \l QStyle::SubControl values. They indicate which subcontrols the complex
259 control consists of and which of them are currently active.
260
261 \section1 QStyle functions
262
263 \l QStyle defines three functions for drawing the primitive, control, and
264 complex elements: \l{QStyle::}{drawPrimitive()},
265 \l{QStyle::}{drawControl()}, and \l{QStyle::}{drawComplexControl()}. They
266 take the arguments listed under \l{Style elements}.
267
268 Not all widgets pass a pointer to themselves. If the style option sent to
269 the function doesn't contain the information you need, check the widget
270 implementation to see whether it passes itself.
271
272 QStyle also provides helper functions for drawing elements.
273 \l{QStyle::}{drawItemText()} draws text within a specified rectangle, taking
274 a \l QPalette as a parameter. \l{QStyle::}{drawItemPixmap()} aligns a pixmap
275 within a specified bounding rectangle.
276
277 Other QStyle functions do calculations for the drawing functions. The
278 widgets also use them to calculate size hints and bounding rectangles when
279 they draw several style elements themselves. These functions typically take
280 the same arguments as the drawing functions.
281
282 \list
283 \li \l{QStyle::}{subElementRect()} takes a \l{QStyle::}{SubElement} value
284 and calculates the bounding rectangle of a subelement. The style uses
285 this function to know where to draw the different parts of an element.
286 If you create a new style, you can reuse the subelement positions of the
287 base class.
288 \li \l{QStyle::}{subControlRect()} calculates the bounding rectangles of the
289 subcontrols in complex controls. When you implement a new style,
290 reimplement it for the rectangles that differ from the base class.
291 \li \l{QStyle::}{pixelMetric()} returns a pixel metric, a style-dependent
292 size given in screen pixels. It takes a value of the
293 \l{QStyle::}{PixelMetric} enum. Pixel metrics don't have to be static
294 measurements; you can calculate them from the style option.
295 \li \l{QStyle::}{sizeFromContents()} returns the size of a widget for a
296 given contents size. Widgets use it to calculate their size hints.
297 \li \l{QStyle::}{hitTestComplexControl()} returns the subcontrol that the
298 mouse pointer is over in a complex control. Usually, this is a matter of
299 using \l{QStyle::}{subControlRect()} to get the bounding rectangles of
300 the subcontrols and finding the one that contains the position of the
301 cursor.
302 \endlist
303
304 QStyle also has the functions \l{QStyle::}{polish()} and
305 \l{QStyle::}{unpolish()}. Qt polishes every widget before it's shown for the
306 first time and again when the style changes, and unpolishes it when the
307 style changes or the widget is destroyed. Use these functions to set
308 attributes on the widgets or to do other work that your style requires. For
309 instance, if you need to know when the mouse is hovering over a widget, set
310 the \l{Qt::}{WA_Hover} widget attribute in \c polish(). The widget then sets
311 \c State_MouseOver in its style options. Overloads of \c polish() also let
312 the style prepare the \l QApplication and adjust the application palette;
313 see \l{The palette}.
314
315 Finally, QStyle has static helper functions for common and difficult tasks.
316 \l{QStyle::}{sliderPositionFromValue()} and
317 \l{QStyle::}{sliderValueFromPosition()} convert between slider values and
318 pixel positions. \l{QStyle::}{visualRect()}, \l{QStyle::}{visualPos()}, and
319 \l{QStyle::}{visualAlignment()} translate logical coordinates and alignments
320 to their mirrored counterparts in right-to-left layouts, and
321 \l{QStyle::}{alignedRect()} aligns a rectangle for the current direction.
322 For details, see \l{QStyle#Right-to-Left Desktops}{Right-to-Left Desktops}
323 in the \l QStyle class documentation.
324
325 When you reimplement QStyle virtual functions, handle the elements that
326 differ from the base class and call the base class implementation for
327 everything else.
328
329 \section1 The palette
330
331 Each style draws with a palette of brushes, provided by \l QPalette. There
332 is one set of colors, a \l QPalette::ColorGroup, for each widget state:
333 active for widgets in the window that has keyboard focus, inactive for
334 widgets in other windows, and disabled for widgets that are disabled. The
335 \c State_Active and \c State_Enabled state flags tell you which group to
336 use. Each group contains the color roles that \l QPalette::ColorRole
337 defines. The roles describe the situations the colors are meant for, such as
338 painting widget backgrounds, text, or buttons.
339
340 Each style decides how to use the color roles. For instance, if the style
341 uses gradients, it can take a palette color and make it darker or lighter
342 with \l QColor::darker() and \l QColor::lighter() to create the gradient. In
343 general, if you need a brush that the palette doesn't provide, derive it
344 from one that it does.
345
346 When you set a style on the application, Qt builds the application palette
347 from the style's \l{QStyle::}{standardPalette()}, lets the platform theme
348 override the roles it provides, and passes the result to
349 \l{QStyle::polish(QPalette &)}{QStyle::polish()}. Reimplement that overload
350 to adjust the colors your style needs. Qt doesn't override a palette that
351 the application set explicitly with \l QApplication::setPalette().
352
353 Don't hard-code colors. Applications and individual widgets can set their
354 own palette, and a style that draws from the palette follows them. It also
355 gets a light and a dark variant from two palettes, without any extra code.
356 Qt's Fusion style works this way:
357
358 \table
359 \row
360 \li \image styles/gallery-fusion-light.webp {Form with text field, combo
361 box, spin box, slider, checkbox, progress bar, and buttons in the Fusion
362 style with a light palette}
363 \li \image styles/gallery-fusion-dark.webp {Form with text field, combo box,
364 spin box, slider, checkbox, progress bar, and buttons in the Fusion
365 style with a dark palette}
366 \endtable
367
368 A style doesn't have to look good with every conceivable palette, but it
369 should honor the palette it's given.
370
371 \section1 Item views
372
373 Delegates paint the items in item views. Qt's default delegate,
374 \l QStyledItemDelegate, draws \c CE_ItemViewItem and calculates item sizes
375 with \c CT_ItemViewItem, so a style controls how items look without an
376 accompanying delegate. The style draws the item view headers, the tree
377 branch indicators, and the row backgrounds directly. To support new data
378 types or item data roles, you need a custom delegate; see
379 \l{Model/View Programming}.
380
381 \section1 Implementation advice
382
383 When you implement a style, read the code of the widgets and of the base
384 class. The widgets use the style in different ways, and the base class
385 implementation can affect the state of the drawing, for example, by altering
386 the \l QPainter state without restoring it, or by drawing some elements
387 without using the appropriate pixel metrics and subelements.
388
389 Don't change the proposed size of widgets in
390 \l{QStyle::}{sizeFromContents()} unless you have to; let the \l QCommonStyle
391 implementation handle it. If you make changes, keep them small. Application
392 development is difficult when the layout of widgets differs considerably
393 between styles.
394
395 Test your style with the \c -reverse command-line option, or with
396 \l QGuiApplication::setLayoutDirection(), so that asymmetric elements also
397 look correct in a right-to-left layout.
398
399 \sa QStyle, QStyleOption, QStylePainter, {Widget Style Reference},
400 {Styling a Checkbox: A Walkthrough}
401*/