StyleSheets (CSS)
Overview
This page provides an overview of CSS-based styling in CDP Studio widgets. While many widgets support visual customization through SVG files, some widgets rely solely on CSS for styling. For example, widgets like scroll bars, group boxes, and frames do not support SVG and are typically styled using CSS rules defined in a stylesheet (e.g., main.css
) applied via the cssFile
property on the main window.
Conversely, certain custom-styled widgets, such as meters, are rendered exclusively using SVG and do not support CSS-based styling. Most interactive widgets like buttons and labels, however, support both SVG and CSS, allowing developers to choose the most suitable method or combine them as needed. This guide explains how to apply CSS rules using the styleSheet
property on individual widgets or globally through an external CSS file. It also outlines best practices, selector syntax, theme integration, and the limitations of CSS styling in the CDP widget system.
See also CDP Widgets Themes (SVG) for SVG-based styling and theme integration.
How to Apply CSS Styling
There are multiple ways to apply CSS styling to widgets. The method depends on the type of widget you're working with.
- Using the
styleSheet
property: You can define custom styling directly on a widget using itsstyleSheet
property.- This is often used for quick overrides or widgets that don’t support external styling.
- See Theme-Based Styling Using Container for an example demonstrating how to use
styleSheet
with theme-aware styling.
- Using the
cssFile
property: For widgets that support external styling, such as buttons and containers, you can assign a.css
file using thecssFile
property.- This allows for more reusable and consistent styling across widgets.
- See Theme-Specific CSS Files for an example demonstrating how to use
cssFile
with theme-aware styling.
- Depending on the widget: For example,
Button
supports both approaches:- Set
type
= NoFile to use thestyleSheet
directly, or to enable styling by parent. - Set
type
= CSS to use an external file via thecssFile
property.
- Set
Widgets without a type
property, such as Frame
, Scrollbar
, and GroupBox
, are automatically styled by the main.css
file provided by the main window. To override the default styling for a specific widget, simply use its styleSheet
property.
Note: CSS styling is inherited from parent widgets to their children. If you want to apply the same style to multiple widgets, it's recommended to place them inside a Container
. The Container
also supports the cssFile
property, which will apply its styles to all its child widgets.
CSS Styling Syntax
Here's a basic example of how to style widgets using a container's cssFile
or styleSheet
property:
CDPBaseButton { background-color: #444; color: white; border-radius: 4px; } CDPBaseLabel { color: black; } CDPBaseLabel[text="warning"] { color: orange; }
In this example:
- All
CDPBaseButton
widgets will have a dark background and rounded corners. - Any
CDPBaseLabel
with itstext
property initially set to"warning"
will be styled in orange; others will remain black by default.
Note: If the CSS is applied on a top-level Container
, all child widgets such as CDPBaseButton
and CDPBaseLabel
must have their stylingType
property set to NoFile
. This allows them to inherit and be styled by the parent container's CSS.
Note: The text
selector only reflects the value when the stylesheet is initially applied. If the text changes at runtime, the style is not updated automatically. To re-evaluate CSS selectors that depend on properties such as text
, you must call the polishStyle()
slot on the container that owns the stylesheet. This will reapply the CSS and update all affected widgets, as described in the following section.
For a complete overview of supported selectors, properties, and pseudo-states, refer to the official Qt Style Sheet Reference:
Reapplying CSS Due to Value Changes
In the earlier example, we used the following CSS rules:
CDPBaseLabel { color: black; } CDPBaseLabel[text="warning"] { color: orange; }
The first rule applies a default black color to all CDPBaseLabel widgets. The second rule overrides this color and applies orange to any label whose text
property is initially set to "warning"
.
However, if the text
property is updated dynamically at runtime, the selector [text="warning"]
is no longer matched, but the style remains unchanged. This is because widget stylesheets are static and do not automatically re-evaluate property-based selectors.
As a result, a label that initially displays the text "warning"
will remain orange even if the text changes to "ok"
, unless the stylesheet is explicitly reapplied.
Assuming a Container is used to provide the stylesheet, there are two ways to reapply the CSS when a value changes.
Manual Refresh
The most direct approach is to add a button that the user can click to trigger a refresh of the container’s stylesheet.
Connect the button’s clicked()
signal to the container’s polishStyle()
slot using a signal and slot connection.
This will reapply the stylesheet on demand. For infrequent updates or low-priority visuals, this approach is typically sufficient.
Automatic Refresh Based on Value Changes
To reapply the stylesheet automatically when a value changes, connect a widget’s signal (typically valueChanged
) to the container’s polishStyle()
slot.
Since CDPBaseLabel
does not emit a signal when its text
changes, it cannot trigger the refresh directly. In such cases, a Com Widget can be used to detect value changes and apply the style update:
- Use a
ComWidget
to receive the value (e.g., a warning string) from the control system. - Connect the
ComWidget’s
valueChanged(QString)
signal to the container’spolishStyle()
slot.
This setup ensures that whenever the value updates (and thus the label text changes), the stylesheet is reapplied and selectors like [text="warning"]
are re-evaluated accordingly.
Making CSS Styling Theme-Aware
To ensure that custom CSS styling adapts to the currently selected theme in CDP Studio, you can use one of two main approaches. Without theme-awareness, styles may become inconsistent or unreadable when switching between themes like flat_gray
or flat_gray_light
.
Theme-Based Styling Using Container
The Container provides a theme
property that reflects the name of the active theme. This allows you to write conditional CSS rules scoped to the theme by targeting this property.
CDPBaseContainer[theme="flat_gray"] CDPBaseLabel { color: red; } CDPBaseContainer[theme="flat_gray_light"] CDPBaseLabel { color: yellow; }
This approach works well for inline styles or shared stylesheets.
Ensure child widgets do not override styling with their own styleSheet
or conflicting stylingType
.
Theme-Specific CSS Files
A cleaner and more scalable approach is to define separate CSS files for each theme. These files are typically placed in dedicated theme folders (e.g., themes/flat_gray/
), and the appropriate file is selected automatically by updating the cssFile
path when the theme changes.
To ensure the CSS files are deployed along with the rest of the UI, place them in the Application directory within the project. This is the same directory that contains the mainwidget.ui
file. The folder can be accessed in CDP Studio Design mode by right-clicking the file in the top selector and choosing Show Containing Folder from the context menu.
In the following example, separate CSS files are used to apply different label colors for the flat_gray
and flat_gray_light
themes. The label will appear red in the flat_gray
theme and yellow in the flat_gray_light
theme.
Directory structure:
themes/ flat_gray/ myStyle.css flat_gray_light/ myStyle.css
Content of themes/flat_gray/myStyle.css
:
CDPBaseLabel { color: red; }
Content of themes/flat_gray_light/myStyle.css
:
CDPBaseLabel { color: yellow; }
Value assigned to the cssFile
property in the Container
:
themes/flat_gray_light/myStyle.css
WebUI note: To use these files in the Web UI, add the folder paths to the WebFilesToServe
property in the Application, using CDP Studio Configure mode:
;themes/flat_gray_light;themes/flat_gray
With this setup, there is no need for conditional logic within the CSS itself. Each file applies only to its corresponding theme, and the system ensures that the correct file is loaded based on the active theme.
Note: To ensure that labels inherit the container's CSS, they must have stylingType
set to NoFile
and an empty styleSheet
.
Setting Properties with CSS
In both of the above approaches, you can also style widget properties using the qproperty-
prefix. This is especially useful for setting text or boolean flags directly from CSS.
Example – Setting Label Text Based on Theme:
CDPBaseContainer[theme="flat_gray"] CDPBaseLabel { qproperty-text: "Red"; } CDPBaseContainer[theme="flat_gray_light"] CDPBaseLabel { qproperty-text: "Yellow"; }
This does not introduce a new styling method, but rather expands the utility of the existing approaches by allowing direct control over widget properties.
Summary
- Use
styleSheet
for inline CSS orcssFile
for external styling, depending on the widget. - Set
stylingType
= NoFile to allow widgets to inherit styles from a parent container. - CSS selectors like
[text="value"]
are only evaluated when the stylesheet is first applied. - Call
polishStyle()
on the container to refresh styling after runtime property changes. - Use the
theme
property or theme-specific CSS files for consistent styling across themes. - Use
qproperty-
syntax to set widget properties such as text, colors, or booleans from CSS.
Get started with CDP Studio today
Let us help you take your great ideas and turn them into the products your customer will love.