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
styling-approaches.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 qtwidgets-styling-approaches.html
6 \title Styling Approaches for Qt Widgets
7 \brief How to choose between a QStyle, StyleKit, and style sheets when
8 styling a Qt Widgets application.
9 \ingroup best-practices
10
11 Qt Widgets offers three ways to change how widgets look:
12
13 \list
14 \li A \l{QStyle}{style} draws every widget. Subclass \l QProxyStyle to
15 adjust the platform style, or \l QCommonStyle to implement a complete
16 custom look. This is the mechanism that Qt's own styles use, and the one
17 to use in production applications.
18 \li \l{Qt Labs StyleKit}{StyleKit} describes a design declaratively in QML
19 and applies it to widgets through \l QStyleKitStyle, a \l QStyle
20 implementation. The same style file also styles Qt Quick Controls.
21 \li \l{Qt Style Sheets}{Style sheets} override individual visual properties
22 with CSS-like rules. They are a tool for prototyping and for small,
23 local adjustments, not for the production look of an application.
24 \endlist
25
26 This page explains what each approach costs and when to choose it.
27
28 \section1 Choose an approach
29
30 The following table maps a styling goal to the mechanism that fits it.
31
32 \table
33 \header
34 \li Goal
35 \li Approach
36 \row
37 \li Keep the native look but change a few details, such as a metric, a
38 color, or a style hint
39 \li A \l QProxyStyle subclass
40 \row
41 \li Give the application its own look, independent of the platform
42 style, for example, on an embedded device
43 \li A \l QCommonStyle subclass or a StyleKit style
44 \row
45 \li Share one design between Qt Widgets and Qt Quick Controls
46 \li A StyleKit style
47 \row
48 \li Offer light and dark variants of the same design
49 \li A different \l QPalette for the same style, or a StyleKit theme
50 \row
51 \li Try out colors, borders, and spacing quickly, or restyle a single
52 widget during development
53 \li A style sheet
54 \endtable
55
56 \section1 Implement a style for production applications
57
58 A \l QStyle subclass draws widgets directly with \l QPainter, using the
59 information in the \l QStyleOption that each widget passes to the style. A
60 style has full control over every element, from a button bevel to the
61 branches of a tree view, and it exercises that control at the cost of an
62 ordinary paint operation: there are no rules to match and no per-widget
63 state to recompute.
64
65 Choose the base class according to how much you want to change:
66
67 \list
68 \li \l QProxyStyle wraps another style, by default the platform style, and
69 lets you override selected functions such as
70 \l{QStyle::drawPrimitive()}{drawPrimitive()},
71 \l{QStyle::pixelMetric()}{pixelMetric()}, or
72 \l{QStyle::styleHint()}{styleHint()}. Everything you don't override
73 keeps the native look and behavior. Use it to adjust the platform style.
74 \li \l QCommonStyle implements the behavior that all of Qt's styles share
75 and leaves the drawing to you. Use it as the base for a complete custom
76 look. \l{Styles and Style Aware Widgets} walks through the style
77 elements and shows how each widget is drawn.
78 \endlist
79
80 Set the style once, before the application creates its windows:
81
82 \snippet customstyle/main.cpp using a custom style
83
84 Draw with the colors from the \l QPalette in the style option rather than
85 with hard-coded colors. The same style then produces a light and a dark
86 variant of the design from two palettes, without switching styles. Qt's
87 Fusion style works this way.
88
89 To let users select the style from the command line with the \c -style
90 option, or to share it between applications, build the style as a plugin.
91 See \l QStylePlugin and \l{How to Create Qt Plugins}.
92
93 \section1 Describe the design in QML with StyleKit
94
95 \l{Qt Labs StyleKit}{StyleKit} is a declarative styling system. A style is a
96 QML file whose root object is a \c Style, which sets colors, sizes, radii,
97 borders, and state-dependent variations for each control type. Properties
98 propagate through a control hierarchy, so a value set once on
99 \c abstractButton applies to every kind of button, and a style can define
100 several named themes.
101
102 \l QStyleKitStyle is a \l QStyle implementation that reads such a style and
103 paints widgets with \l QPainter. Qt Quick takes no part in the rendering.
104 The same \c Style file also styles Qt Quick Controls, so an application that
105 uses both toolkits maintains one design definition. Themes defined in the
106 style are selected with \l{QStyleKitStyle::setThemeName()}{setThemeName()}.
107
108 \code
109 auto *style = new QStyleKitStyle(QStringLiteral(":/styles/MyStyle.qml"));
110 QApplication::setStyle(style);
111 \endcode
112
113 \l QStyleKitStyle is available since Qt 6.12. StyleKit is a Qt Labs module,
114 and its API may change between Qt releases. The \l{StyleKit Widgets Example}
115 shows a widget application with several StyleKit styles and themes.
116
117 \section1 Use style sheets for prototyping
118
119 \l{Qt Style Sheets} change the appearance of widgets through rules in a
120 CSS-like syntax, without writing C++. They are convenient for trying out a
121 design: edit a \c{.qss} file and restart the application, or pass the file
122 with the \c -stylesheet command-line option, and
123 \l{Qt Widgets Designer Integration}{Qt Widgets Designer} previews the same
124 rules. They are also the quickest way to mark a single widget, such as a
125 mandatory field with a yellow background.
126
127 Style sheets have costs that make them unsuitable as the styling mechanism
128 of a production application:
129
130 \list
131 \li \b{Every affected widget is drawn through the style sheet engine.} When
132 a style sheet is set, \l QWidget::style() returns a style sheet style
133 that wraps the underlying \l{QStyle}{style}. For each widget it matches
134 the selectors against the widget's class, object name, properties, and
135 state, computes the rendering rules, and caches them per widget. The
136 memory and processing cost grows with the number of widgets and rules.
137 \li \b{Changing a style sheet repolishes everything it applies to.} Each
138 call to \l QApplication::setStyleSheet() discards the caches and
139 repolishes every widget in the application, which recomputes fonts,
140 palettes, geometry, and size hints and can visibly flicker. Don't build
141 theme switching on style sheets.
142 \li \b{A partial rule discards the native look.} When a rule requests
143 something the native style cannot honor, such as a background color for
144 a \l QPushButton, the style sheet engine draws the whole element itself,
145 without the native decoration. You then have to specify borders,
146 padding, and every state yourself, and a small adjustment grows into a
147 complete description of the look. See
148 \l{Customizing Qt Widgets Using Style Sheets}.
149 \li \b{Selectors couple the design to implementation details.} Rules match
150 class names, object names, and property values. Renaming an object or
151 replacing a widget class silently stops the rule from matching. Rules
152 don't affect custom widgets that paint without the style.
153 \li \b{Style sheets win over programmatic settings.} A style sheet overrides
154 fonts, palettes, and item colors set with functions such as
155 \l QWidget::setFont() or \l QTreeWidgetItem::setBackground(), so the
156 styling of a widget is no longer visible in one place.
157 \endlist
158
159 For a side-by-side comparison of style sheets and \l QStyle subclasses, see
160 the KDAB article \l {https://www.kdab.com/say-no-to-qt-style-sheets/}
161 {Say No to Qt Style Sheets}.
162
163 \section2 If you use style sheets anyway
164
165 For a prototype, or for the few local adjustments that a production
166 application needs, keep the style sheet manageable:
167
168 \list
169 \li \b{Keep the rules in a \c{.qss} file}, bundled with
170 \l{The Qt Resource System}{the Qt resource system}. Set it once on the
171 application with \l QApplication::setStyleSheet(), before the first
172 window is shown, and leave it in place. Reserve
173 \l QWidget::setStyleSheet() for adjustments that are truly local to one
174 widget and its children.
175 \li \b{Don't assemble style sheets from C++ strings.} A style sheet set on a
176 widget is parsed once for every widget it's set on, not once for every
177 string, and each call to \l QWidget::setStyleSheet() repolishes the
178 widget and all its children, even when the string didn't change. A
179 string built with \l QString::arg() to reflect data, such as a red
180 border for an invalid value, repolishes the widget on every update.
181 Instead, express the difference with a
182 \l{The Style Sheet Syntax}{selector} on an object name or a Qt property
183 in the one style sheet, and re-evaluate it as described in
184 \l{Customizing Using Dynamic Properties}.
185 \li \b{Don't hard-code colors.} A literal color such as \c{#ffffff} fits one
186 theme. Use \c{palette(window)}, \c{palette(text)}, and the other
187 \l{PaletteRole}{palette roles} so that the style sheet follows the
188 application palette, including a dark color scheme.
189 \li \b{Don't size everything in pixels.} A \c px value scales with the
190 display but not with the user's font. Use \c em and \c ex
191 \l{Length}{lengths} for paddings, margins, and sizes that should follow
192 the font, and \c pt for font sizes.
193 \endlist
194
195 \section2 Move from a style sheet to a style
196
197 When a prototype turns into a product, transfer the design to a style. Most
198 style sheet constructs have a direct counterpart:
199
200 \table
201 \header
202 \li Style sheet
203 \li QStyle
204 \li StyleKit
205 \row
206 \li Colors
207 \li \l QPalette roles, read from \l QStyleOption::palette
208 \li Color properties of the control, or a theme
209 \row
210 \li \c border, \c padding, \c margin
211 \li \l{QStyle::pixelMetric()}{pixelMetric()} and
212 \l{QStyle::subElementRect()}{subElementRect()}
213 \li Border and size properties of the control
214 \row
215 \li Pseudo-states such as \c{:hover} and \c{:pressed}
216 \li \l QStyle::State flags in \l QStyleOption::state
217 \li State groups such as \c hovered and \c pressed
218 \row
219 \li Subcontrols such as \c{::indicator}
220 \li \l{QStyle::drawPrimitive()}{drawPrimitive()} and
221 \l{QStyle::drawControl()}{drawControl()} for the element
222 \li Delegate properties such as \c indicator
223 \endtable
224
225 \sa {Styles and Style Aware Widgets}, QStyle, QProxyStyle, QCommonStyle,
226 {Qt Labs StyleKit}, {Qt Style Sheets}
227*/