Chapter 26. Elements with Style

Have you ever encountered a situation where your application “kind of works” but looks like it was assembled from different eras and platforms? Every developer knows this feeling: the functionality is ready, but the look & feel suddenly turns into a quiet disaster for user trust.

This chapter reveals a non-obvious fact: appearance isn’t just “cosmetics,” but part of sales and UX logic. Here you’ll discover how to achieve nativeness across different OSes while maintaining a recognizable product style—without rewriting half the UI.

The chapter covers 3 built-in styles (including Fusion), on-the-fly style switching via QStyleFactory, and granular customization through QStyle / QCommonStyle and methods drawPrimitive(), drawControl(), drawComplexControl(). Plus—QSS (Qt CSS): selectors, states :hover/:pressed/:checked, subelements, and border-image without recompilation.

If your application’s style is still “default,” you risk losing before the first click.

This chapter includes ready-to-use code examples.

Chapter Self-Check

Why are Qt styles independent of program code and what advantage does this provide for development?Answer
Correct answer: This allows separating teams into programmers and designers who work independently; created styles can be used in other Qt projects without modifying the source code.
Which class should be inherited to create a custom style and why not inherit directly from QStyle?Answer
Correct answer: It’s preferable to inherit from QCommonStyle, as it defines commonly used methods and requires less effort than overriding all methods of the abstract QStyle class.
Why is the Qt::WA_Hover attribute set for buttons in the polish() method?Answer
Correct answer: So that Qt creates a repaint event every time the mouse pointer enters the button area, allowing changes to its appearance on hover.
What happens if you create a style object via new and pass it to setStyle(), forgetting to call delete later?Answer
Correct answer: No memory leak occurs, as the QApplication class takes responsibility for destroying style objects and automatically deletes the old object when a new one is set.
What key role does the QStyleOption class play when drawing controls?Answer
Correct answer: It passes all necessary information about the widget (state, dimensions, font, palette) to drawing methods, allowing correct element display without direct access to the widget.
What is the fundamental difference between the drawPrimitive(), drawControl(), and drawComplexControl() methods?Answer
Correct answer: drawPrimitive() draws simple elements (indicators, frames), drawControl() — basic widgets (buttons, progress bars), and drawComplexControl() — composite elements with multiple parts (scrollbars, spinboxes).
Why is using CSS styles considered a more efficient approach than inheriting style classes in C++?Answer
Correct answer: CSS doesn’t require C++ knowledge, allows involving designers without programming skills, and doesn’t require recompilation when changing styles, significantly speeding up development.
What happens if you write QPushButton in CSS instead of .QPushButton?Answer
Correct answer: The style will be applied to all classes inherited from QPushButton; the dot before the class name excludes applying the style to inherited classes.
Why is the border-image property with 9 image parts needed when styling buttons?Answer
Correct answer: It protects corner parts (e.g., rounded corners) from deformation when the button size changes, stretching only the side and center parts of the image.
How do you apply a CSS style only to widgets with a specific object name set via setObjectName()?Answer
Correct answer: Use the Class#ObjectName syntax, for example: QLabel#MyLabel will apply the style only to QLabel with object name MyLabel.
What happens if you combine states with a comma: QCheckBox:hover, QCheckBox:checked?Answer
Correct answer: The style will be applied when the widget is in ANY of the specified states (logical OR), not simultaneously in both.
Why was a horizontal gradient used instead of a vertical one for the :pressed state in gradient examples?Answer
Correct answer: So the user immediately notices the visual difference and understands that the button state has changed—the horizontal direction creates contrast with the usual vertical gradient.
How do you activate a dark theme in Qt6 using the built-in Fusion style?Answer
Correct answer: Set the Fusion style via setStyle(), then create a dark QPalette with color settings for Window, Text, Button, and other roles, and apply it via setPalette().
What is the purpose of a double-colon selector, such as QComboBox::drop-down?Answer
Correct answer: To access subelements of composite widgets—in this case, the dropdown arrow button, allowing independent styling of widget parts.
Why does the chapter author emphasize the importance of program appearance, comparing it to choosing a car or meeting people?Answer
Correct answer: Appearance is the first thing a user sees; an attractive interface creates the desire to try the program, without which the user will never appreciate its functional capabilities.

Practical Exercises

Easy Level

Real-time Style Switcher
Create an application with several widgets (button, checkbox, slider, input field) and a dropdown list for selecting styles. When selecting a style from the list, all widgets should instantly change their appearance. Add all available Qt built-in styles.
Hints: Use QStyleFactory::keys() to get the list of styles. Create a QComboBox and connect the textActivated signal to a slot that calls setStyle(QStyleFactory::create()). Arrange widgets in a vertical layout.

Medium Level

Button with CSS State Animation
Create a checkable button that has different visual states: normal, on mouse hover, pressed, activated, and activated with hover. Use CSS with gradients and transparency effects. The button should show its current state (e.g., “ON” or “OFF”).
Hints: Use setCheckable(true) for the button. In CSS, define styles for states :hover, :pressed, :checked, and :checked:hover. Apply qlineargradient for gradients. Use the rgba() function for transparency. Connect the toggled signal to a slot to change the button text.

Hard Level

Custom Style with drawPrimitive() Override
Create a custom style class inheriting from QCommonStyle that customizes the display of buttons, checkboxes, and radio buttons. Override the drawPrimitive() and polish()/unpolish() methods. Implement loading images from resources for different element states (normal, hover, pressed). Add the ability to switch between your style and standard Qt styles.
Hints: Create a class inheriting from QCommonStyle. In polish(), set Qt::WA_Hover for widgets. In drawPrimitive(), handle PE_PanelButtonCommand, PE_IndicatorCheckBox, PE_IndicatorRadioButton. Use qstyleoption_cast to get state information. Check flags State_Sunken, State_MouseOver, State_Enabled. Create a resource file (.qrc) with images. In the default section, call QCommonStyle::drawPrimitive().

💬 Join the Discussion!

Figured out the difference between QStyle and CSS approach? Have questions about when it’s better to use drawPrimitive() and when CSS styles are enough?

Share your styling examples, show created button designs, or ask questions about gradients and border-image!

Discuss with other readers how you apply “beautiful interface” principles in your projects. Your experience can help beginner developers!

Leave a Reply

Your email address will not be published. Required fields are marked *