QSS基本使用方法
Qt QSS 选择器和 CSS2、CSS3 的选择器类似,建议先学习或者复习 CSS 选择器的语法。
QSS 虽然源自 CSS ,但也有稍许不同,而且支持的语法也没 CSS 那么多。
选择器类型
类选择器
1 | /* |
选择器分组
1 | /*同时匹配QPushButton、QLineEdit的实例 |
ID 选择器
1 | /* |
属性选择器
1 | /* |
后代选择器
1 | /* |
子元素选择器
1 | /* |
伪状态
1 | /* |
子控件选择器
1 | QRadioButton::indicator::unchecked:disabled { |
选择器优先级
一句话归纳为:优先使用更具体的选择器。
具体实例如下:
1 | /* |
1 | /* |
1 | /* |
1 | /* |
1 | /* |
类型、属性、伪状态、子控件
关于 QSS 支持哪些类型、每种类型支持哪些属性、伪状态和子控件,在 Qt 的官方的英文文档中有详细的介绍:
《Qt Style Sheets Reference》
也可以在 Qt Assistant 中搜索”Qt Style Sheets Reference”打开帮助文档。
3.1 伪状态列表
为了方便查阅,这里列举出 QSS 目前支持的所有伪状态。
伪状态都是以一个冒号
:开头,如:active。
| 伪状态 | 描述 |
|---|---|
| :active | 此状态在 Widget 驻留在活动窗口时设置 |
| :adjoins-item | 此状态在 QTreeView 的::branch 与一个 item 相邻时设置 |
| :alternate | 当 QAbstractItemView::alternatingRowColors()设置为真时,在绘制 QAbstractItemView 的行时,为每个交替行设置此状态 |
| :bottom | 此 item 位于底部时设置。例如,QTabBar 有位于底部的选项卡 |
| :checked | 此 item 被选中时设置。例如,QAbstractButton 的 checked 状态 |
| :closable | 此 item 可以被关闭时设置。例如,QDockWidget 的 QDockWidget::DockWidgetClosable 特性开启时 |
| :closed | 此 item 处于关闭状态时设置。例如,QTreeView 中未展开的 item |
| :default | 此 item 的默认状态时设置。例如,一个 default 的 QPushButton 或 QMenu 中的一个默认动作 |
| :disabled | 此 item 被禁用时设置 |
| :editable | 如 QComboBox 是可编辑时设置 |
| :edit-focus | 此 item 具有编辑焦点(参考 QStyle::State_HasEditFocus)时设置。此状态仅对 Qt 扩展应用程序可用 |
| :enabled | 此 item 已启用时设置 |
| :exclusive | 此 item 是属于某个独占组时设置。例如,独占 QActionGroup 中的菜单项 |
| :first | 此 item 是列表中的第一项时设置。例如,QTabBar 中的第一个选项卡 |
| :flat | 此 item 是扁平时设置。例如,一个扁平的 QPushButton |
| :floatable | 此 item 可以浮动时设置。例如,QDockWidget 的 QDockWidget::DockWidgetFloatable 的特性开启时 |
| :focus | 此 item 具有输入焦点时设置 |
| :has-children | 此 item 具有子对象时设置。例如,QTreeView 中具有子项的项 |
| :has-sibling | 此 item 具有兄弟对象时设置。例如,QTreeView 中与之相邻的项 |
| :horizontal | 此 item 处于水平方向时设置 |
| :hover | 鼠标悬浮在此 item 上时设置 |
| :indeterminate | 此 item 处于不确定状态时设置。例如,QCheckBox 或 QRadioButton 被部分选中 |
| :last | 此 item 是列表中的最后一项时设置。例如,QTabBar 中的最后一个选项卡 |
| :left | 此 item 位于左侧时设置。例如,QTabBar 有位于左侧的选项卡 |
| :maximized | 此 item 处于最大化状态时设置。例如,一个最大化的 QMdiSubWindow |
| :middle | 此 item 是列表中的中间一项时设置。例如,一个不在 QTabBar 中的开头或结尾的选项卡 |
| :minimized | 此 item 处于最小化状态时设置。例如,一个最小化的 QMdiSubWindow |
| :movable | 此 item 可以被移动时设置。例如, QDockWidget 的 QDockWidget::DockWidgetMovable 特性开启时 |
| :no-frame | 此 item 没有边框时设置。例如,没有边框的 QSpinBox 或 QLineEdit |
| :non-exclusive | 此 item 是属于非独占组时设置。例如,非独占 QActionGroup 中的菜单项 |
| :off | 对可以切换的 items,这适用于处于 off 状态的 item |
| :on | 对可以切换的 items,这适用于处于 on 状态的 widget |
| :only-one | 此 item 是列表中的唯一项时设置。例如,一个在 QTabBar 中单独的选项卡 |
| :open | 此 item 处于打开状态时设置。例如,QTreeView 中的展开项,或带有菜单的 QComboBox 或 QPushButton |
| :next-selected | 此 item 是列表中的下一个被选中的项时设置。例如,在 QTabBar 中当前选项卡的下一个要选中的选项卡 |
| :pressed | 鼠标正在按压在此 item 上时设置 |
| :previous-selected | 此 item 是列表中的上一个被选中的项时设置。例如,在 QTabBar 中当前选项卡的上一个要选中的选项卡 |
| :read-only | 此 item 处于只读或不可编辑状态时设置。例如,一个只读 QLineEdit 或不可编辑的 QComboBox |
| :right | 此 item 位于右侧时设置。例如,QTabBar 有位于右侧的选项卡 |
| :selected | 此 item 处于选中状态时设置。例如,一个在 QTabBar 中被选中的选项卡或一个在菜单中被选中的菜单项 |
| :top | 此 item 位于顶部时设置。例如,QTabBar 有位于顶部的选项卡 |
| :unchecked | 此 item 处于未被选中状态时设置 |
| :vertical | 此 item 处于垂直方向时设置 |
| :window | Widget 是一个窗口(例如,一个顶层 Widget)时设置 |
3.2 子控件列表
伪状态都是以两个冒号
::开头,如::item。
| 子控件 | 描述 |
|---|---|
| ::add-line | 在 QScrollBar 中跳转下一行的按钮 |
| ::add-page | 在 QScrollBar 中滑动条和 add-line 之间的区域 |
| ::branch | 在 QTreeView 中的分支指示器 |
| ::chunk | 在 QProgressBar 中的进度块 |
| ::close-button | 在 QDockWidget 或 QTabBar 选项卡的关闭按钮 |
| ::corner | 在 QAbstractScrollArea 中两个滚动条之间的角落 |
| ::down-arrow | 在 QComboBox、QHeaderView(排序指示器)、QScrollBar 或 QSpinBox 的向下箭头 |
| ::down-button | 在 QScrollBar 或 QSpinBox 中的向下按钮 |
| ::drop-down | 在 QComboBox 中的下拉框 |
| ::float-button | 在 QDockWidget 中的浮动按钮 |
| ::groove | 在 QSlider 中的滑动槽 |
| ::indicator | 在 QAbstractItemVIew、QCheckBox、QRadioButton、可选中的菜单项或可选中的 QGroupBox 中的指示器 |
| ::handle | 在 QScrollBar、QSplitter 和 QSlider 中的操作条(滑动条) |
| ::icon | 在 QAbstractItemVIew 或 QMenu 中的图标 |
| ::item | 在 QAbstractItemVIew、QMenuBar、QMenu 或 QStatuBar 中的一项 |
| ::left-arrow | 在 QScrollBar 中的向左箭头 |
| ::left-corner | 在 QTabWidget 中的左上角 |
| ::menu-arrow | 带有菜单的 QToolButton 中的箭头 |
| ::menu-button | 在 QToolButton 中的菜单按钮 |
| ::menu-indicator | 在 QPushButton 中的菜单指示器 |
| ::right-arrow | 在 QMenu 或 QScrollBar 中的向右箭头 |
| ::pane | 在 QTabWidget 中的边或框 |
| ::right-corner | 在 QTabWidget 中的右上角 |
| ::scroller | 在 QMenu 或 QTabBar 中的滚动条 |
| ::section | 在 QHeaderView 中的区块 |
| ::separator | 在 QMenu 或 QMainWIndow 中分隔条 |
| ::sub-line | 在 QScrollBar 中跳转上一行的按钮 |
| ::sub-page | 在 QScrollBar 中滑动条和 sub-line 之间的区域 |
| ::tab | 在 QTabBar 或 QToolBox 中选项卡 |
| ::tab-bar | 在 QTabWidget 中的选项卡栏 |
| ::tear | 在 QTabBar 中的 tear 指示器 |
| ::tearoff | 在 QMenu 中的 tear-off 指示器 |
| ::text | 在 QAbstractItemView 中的文本 |
| ::title | 在 QGroupBox 或 QDockWidget 中的标题栏 |
| ::up-arrow | 在 QComboBox、QHeaderView(排序指示器)、QScrollBar 或 QSpinBox 的向上箭头 |
| ::up-button | 在 QScrollBar 或 QSpinBox 中的向上按钮 |
使用示例:
1 | QPushButton#btnTest::menu-indicator { |
同时使用伪状态和子控件时,先指定子控件,后指定伪状态:
1 | QComboBox::down-arrow:disabled { |
盒子模型
在使用 QSS 设置样式时,有一个关键的概念需要知晓,那就是“盒子模型”(即Box Model)。

每个 Widget 都被视为具有 4 个同心矩形的框:
MARGIN 矩形、BORDER 矩形、PADDING 矩形和 CONTENT 矩形,上图标注了每个矩形的区域。
默认情况下 MARGIN 矩形、BORDER 矩形、PADDING 矩形的宽度都为 0,这样在默认情况下,4 个矩形就重合为 1 个 CONTENT 矩形了。
同样,默认情况下 background-image 指定的背景,只在 border 内的区域绘制,但我们也可以使用 background-clip 或 background-origin 属性来更改这种默认行为。
如何实现背景图像随 Widget 大小自动缩放?
background-image 指定的背景图像无法随 Widget 大小自动缩放,要提供可以随 Widget 大小缩放的背景图像可以使用border-image和image属性,二者区别如下:
- border-image 属性指定的图像从 border 及其内的区域开始绘制,会导致 border 属性被覆盖。
- image 属性指定的图像从绘制到 content 区域内,image 指定的 url 为 SVG 图像,则支持自动缩放,非 SVG 图像仅支持自动缩小。
动态属性
通过 setProperty 方法设置 QWidget 对象属性,在 QSS 中可以根据不同的属性值应用不同的样式。
例如,设置 pushButtonMax 按钮的 isMax 属性,表示当前窗口是否最大化:
1 | pushButtonMax->setProperty("isMax", this->isMaximized() ? true : false); |
在 QSS 中根据不同的属性值应用不同的样式:
1 | #pushButtonMax[isMax="false"] { |
Q_PROPERTY
在 Qt 中可以使用Q_PROPERTY宏为 QObject 对象(含子对象)声明属性,任何被Q_PROPERTY声明的属性都能在 QSS 中使用qproperty-<property name>语法进行设置。
以 QToolButton 为例,QToolButton 继承至 QAbstractButton,QAbstractButton 拥有以下被 Q_PROPERTY 声明的属性:
1 | class Q_WIDGETS_EXPORT QAbstractButton : public QWidget |
在 QSS 中可以直接对属性赋值,如:
1 | QToolButton { |
Padding 和 Margin 的使用
Margin 指控件和其他控件的间距,而 Padding 指控件内的内容与边框的间距。
二者的语法与 CSS 中的一样:
1 | margin: 25px 50px 75px 100px; |
从左到右依次为:上、右、下、左。
支持简写形式:
1 | margin: 25px 50px; |
表示:上下间距为 25px,左右间距为 50px。
几种图片设置方法
大家在使用 QSS 进行图片设置时,也许被 image, border-image, background-image 这几个属性的差异困扰过,下面就来讲解一下这个几个属性的异同点。
background-image
background-image 按图片实际尺寸显示图片,超过控件显示区域的部分会被裁剪掉。
虽能显示 SVG,但无法对 SVG 进行无损缩放;
关于 background-image 的几个附属属性的作用,可以一句话概括为:
从 background-origin 区域的 background-position 位置开始绘制图像,并以 background-repeat 方式进行重复;最后将图像 background-clip 区域以外的范围裁剪掉(即不显示)。
image
image 会将图片按图片原长宽比进行缩放,并保证填充满控件 content 区域。
image 支持 SVG 矢量图显示和无损缩放。
image 可以使用 image-position 来指定图片开始显示的位置(参考上面background-position)。
border-image
按控件 border 区域的长宽比来缩放图片,保证填充满控件 border 区域,支持 SVG 矢量图显示和无损缩放;
绘制顺序
如果在一个控件中同时指定 background-image,border-image,image 这三个属性,会按照如下的顺序进行绘制:
1 | 先绘制 background-image |
示例
1 | QPushButton#pushButton4 { |

QSS 编辑器
QSS 样式的编写是一个熟能生巧的过程,不仅不需要熟记常用的样式属性,还需要勤加练习,多多验证,灵活运用。
为了方便学习和验证 QSS 样式,我开发了一个 QSS 编辑器,通过该编辑器可以实时预览 QSS 的生效样式,而且编辑器还内置了两套完整的 QSS 主题,方便初学者学习 QSS 属性。
项目地址: