一、什么是 QSS?
QSS(Qt Style Sheets) 是 Qt 框架提供的一种样式表机制,用于自定义控件的外观。它的语法大量参考了 Web 开发中的 CSS,但功能相对较弱:可用的选择器类型更少,支持的样式属性也有限,并且并非所有属性都能应用于任意控件。
不过,QSS 已经足以帮助我们实现大多数常见的界面美化需求,例如设置背景色、字体、边框、圆角、悬停效果等。
二、QSS 的使用方法
2.1 基本步骤
-
编写 QSS 样式文本(通常保存在
.qss文件中)。 -
在程序中读取该文件内容。
-
调用控件的
setStyleSheet()方法应用样式。
2.2 代码示例
cpp
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent),
ui(new Ui::MainWidget)
{
// 加载 qss 文件
QFile file(":/qss/main.qss");
file.open(QFile::ReadOnly);
QTextStream filetext(&file);
QString stylesheet = filetext.readAll();
file.close();
// 应用到当前窗口及其所有子控件
this->setStyleSheet(stylesheet);
}
注意 :setStyleSheet() 是 QWidget 的成员函数,因此几乎任何控件都可以单独设置自己的样式表。
三、QSS 语法规则
QSS 的语法规则与 CSS 基本一致,由 选择器 和 声明块 组成:
选择器 { 属性: 值; 属性: 值; ... }
示例
QPushButton { color: red; }
这条规则的意思是:将所有 QPushButton 及其子类的文字颜色设置为红色。
与 CSS 的不同之处 :
在 CSS 中,选择器
div只匹配<div>标签;而在 QSS 中,类型选择器QPushButton不仅匹配QPushButton本身,还匹配所有继承自QPushButton的子类(例如MyButton)。
如果只想匹配确切的 QPushButton 类(不包括子类),可以使用 类选择器(前面加一个点):
.QPushButton { color: red; } // 只匹配 QPushButton,不匹配子类
四、QSS 选择器类型
| 选择器类型 | 语法示例 | 说明 |
|---|---|---|
| 通配选择器 | * |
匹配所有控件 |
| 类型选择器 | QPushButton |
匹配该类及其子类的所有实例 |
| 类选择器 | .QPushButton |
只匹配该类本身,不匹配子类 |
| ID 选择器 | #myButton |
匹配 objectName 为 myButton 的控件 |
| 属性选择器 | QPushButton[flat="false"] |
匹配 flat 属性为 false 的按钮(属性可以是自定义的) |
| 后代选择器 | QDialog QPushButton |
匹配 QDialog 内任意层级 的 QPushButton |
| 子选择器 | QDialog > QPushButton |
匹配 QDialog 直接子容器 中的 QPushButton |
组合使用
多个选择器可以组合,也可以使用逗号同时为多个选择器指定同一套规则:
cpp
/* 组合后代选择器 */
#mytable QPushButton { background: gray; }
/* 多选择器共用规则 */
#frameCut, #frameInterrupt, #frameJoin { border: 1px solid black; }
五、子控件选择器
对于 复合控件 (如 QComboBox、QSpinBox 等),我们可以通过 子控件选择器 来定制其内部的某个部分。
子控件选择器使用双冒号 :: 表示,例如:
QComboBox::drop-down { image: url(dropdown.png); }
这行代码将 QComboBox 的下拉按钮图片替换为自定义图片。
也可以与其他选择器结合:
QComboBox#myQComboBox::drop-down { image: url(dropdown.png); }
常见子控件 :
::drop-down(下拉按钮)、::down-arrow(向下箭头)、::up-button(上调节按钮)、::tab-bar(标签栏)等。具体列表可查阅 Qt 帮助文档。
六、伪状态选择器
伪状态选择器用于匹配控件在特定状态下的样式。它使用冒号 : 开头,且必须放在选择器的最后面。
示例
cpp
/* 鼠标悬停时背景变红 */
QComboBox:hover { background-color: red; }
/* 鼠标悬停在下拉箭头上时背景变红 */
QComboBox::drop-down:hover { background-color: red; }
伪状态的逻辑运算
-
取反 :使用
!,例如:!hover表示非悬停状态。 -
组合 :多个伪状态可以连写,如
:hover:checked。
cpp
QCheckBox:hover:checked { color: white; }
Qt 提供了大量伪状态,如 :checked(选中)、:disabled(禁用)、:focus(获得焦点)、:pressed(按下)等,具体可查阅官方文档。
七、级联与冲突
7.1 冲突解决:特异性(权重)
当多个规则同时作用于同一控件的同一属性时,QSS 根据 特异性(权重)来决定最终应用哪个规则。
权重计算规则(与 CSS 一致):
-
统计规则中 ID 选择器 的个数 → 记为
a -
统计 类选择器、属性选择器、伪状态 的个数 → 记为
b -
统计 类型选择器 (如
QPushButton)的个数 → 记为c
最终权重为 a b c(按位比较)。权重值越大,优先级越高。
示例:
cpp
* { color: black; } /* a=0, b=0, c=0 → 权重 0 */
QPushButton { color: red; } /* a=0, b=0, c=1 → 权重 1 */
QPushButton:hover { color: blue; } /* a=0, b=1, c=1 → 权重 11 */
#okButton { color: green; } /* a=1, b=0, c=0 → 权重100 */
因此,#okButton 的规则会覆盖前面所有规则。
如果两条规则权重相同,则后出现的规则生效。
7.2 继承与级联
-
一个控件可以同时受到 父控件 和 自身 上设置的样式影响,最终效果是合并所有适用的样式。
-
如果发生冲突(同一属性在不同层级被设置),子控件自己的样式 优先级最高。
示例:
cpp
qApp->setStyleSheet("QPushButton { color: white; }");
myButton->setStyleSheet("* { color: blue; }");
最终 myButton 的文字颜色为蓝色(自身样式覆盖了全局样式)。
注意 :父控件设置的样式不会自动被子控件继承,除非该样式明确选择了子控件。例如:
cpp
// 这个样式只影响 QFrame 本身,不会影响其内部的 QPushButton
ui->frame->setStyleSheet("QFrame { color: red; }");
// 这个样式会影响 frame 内所有的 QPushButton
ui->frame->setStyleSheet("QPushButton { color: red; }");
八、实际应用中的注意事项
8.1 边框设置的属性顺序
正确写法:
cpp
border: 1px solid red; /* 宽度 样式 颜色 */
错误写法(顺序随意会导致无效):
cpp
border: solid 1px red; /* 无效 */
border: red 1px solid; /* 无效 */
border: red solid 1px; /* 无效 */
8.2 设置控件的宽高
在 QSS 中直接使用 width 和 height 通常无效。正确的做法是使用:
-
min-width/min-height -
max-width/max-height
cpp
QPushButton {
min-width: 80px;
min-height: 30px;
max-width: 120px;
}
8.3 QComboBox 的样式定制
QComboBox 是一个复杂的复合控件,需要分别定制其不同部分。
| 选择器 | 作用 |
|---|---|
QComboBox |
组合框主体(未弹出下拉列表时) |
QComboBox::drop-down |
下拉按钮 |
QComboBox::down-arrow |
下拉箭头图标 |
QComboBox QAbstractItemView |
弹出的下拉列表的整个矩形区域 |
QComboBox QAbstractItemView::item |
下拉列表中的每一个选项 |
示例:
cpp
/* 下拉列表整体样式 */
QComboBox QAbstractItemView {
border: 1px solid gray;
background: white;
}
/* 下拉列表项样式(需要先设置 item delegate 才能生效) */
QComboBox QAbstractItemView::item {
height: 30px;
padding: 5px;
}
注意 :要使 ::item 样式生效,必须为 QComboBox 设置 QStyledItemDelegate:
cpp
QStyledItemDelegate* delegate = new QStyledItemDelegate();
comboBox->setItemDelegate(delegate);
九、总结
本文系统介绍了 Qt 中 QSS 的核心知识:
-
什么是 QSS:Qt 的样式表语言,类似 CSS。
-
如何使用 :读取
.qss文件并调用setStyleSheet()。 -
选择器系统:类型、类、ID、属性、后代、子选择器,以及子控件和伪状态。
-
级联与冲突:权重计算规则和优先级。
-
常见坑点 :边框属性顺序、宽高设置、
QComboBox的特殊处理。
掌握这些内容后,你已经能够灵活运用 QSS 美化 Qt 应用程序的界面。如果需要更详细的信息,建议查阅 Qt 官方文档中关于 Qt Style Sheets 的章节。