On this page

Writing Style-Aware Widgets

A style-aware widget conforms to the style in which it's drawn. Instead of painting frames, buttons, and indicators itself, it asks the current style to draw them, and it asks the style for the metrics it needs to lay out its contents. The widget then looks native on every platform, follows the application palette, and picks up a custom style or a style sheet like Qt's own widgets do.

Build a style option

The style draws from the information in a QStyleOption, so the first step in a paint event is to fill one out. Pick the option class that matches the element you want to draw, call QStyleOption::initFrom() to set the state flags, rectangle, palette, and font metrics that every widget shares, and then set the members that are specific to your element.

Qt's widgets do this in a protected virtual initStyleOption() function, so that subclasses can adjust the option. Follow the same pattern in your widget.

Draw through the style

Draw the elements with the drawing functions of QStyle, passing the option, a QPainter, and the widget itself:

QPainter painter(this);
    ...
style()->drawPrimitive(QStyle::PE_FrameFocusRect, &option, &painter, this);

QStylePainter combines a QStyle, a QPainter, and a QWidget. Its drawing functions take the element and the option only, which makes the code shorter:

    QStylePainter painter(this);
    ...
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);

Diagram showing QStylePainter inherits from QPainter

Use the palette in the option, or QWidget::palette(), for any color you draw yourself, so that the widget follows the application palette and works in both light and dark color schemes.

Ask the style for sizes

Base your sizeHint() and minimumSizeHint() on the style. sizeFromContents() turns the size of your contents into the size of the widget for a given contents type, and pixelMetric() returns the style's frame widths, margins, and indicator sizes. Use subElementRect() to find out where the style places the parts of an element, instead of computing the positions yourself.

Report the widget's state

The style draws hover and focus effects only if the state flags are set. Set the WA_Hover attribute on your widget to receive hover events, and add State_MouseOver to the option while the mouse is over the element. Set State_Sunken while the widget is pressed, and State_On, State_Off, or State_NoChange for checkable elements. Widget Style Reference lists the flags that each element expects.

Follow style and palette changes

When the application style or palette changes, the widget receives a QEvent::StyleChange or QEvent::PaletteChange event in changeEvent(). Invalidate any cached metrics there and call updateGeometry() if your size hint depends on the style.

Support right-to-left layouts

In a right-to-left layout, the style mirrors asymmetric elements. Use visualRect() to convert a rectangle from logical to screen coordinates and visualAlignment() to mirror an alignment, and pass the option's direction through to the style. Test with the -reverse command-line option.

See also QStyle, QStylePainter, QStyleOption, How a Style Draws a Widget, and Widget Style Reference.

© 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.