样式表语法
Qt 样式表的术语和语法规则与 HTML CSS 几乎完全相同。如果您已经了解 CSS,那么可以快速浏览本节内容。
样式规则
样式表由一系列样式规则组成。一条样式规则由选择器和声明构成。选择器指定哪些控件受该规则影响;声明指定应为控件设置哪些属性。例如:
QPushButton { color: red }在上述样式规则中,QPushButton 是选择器,{ color: red } 是声明。该规则指定QPushButton 及其子类(例如MyPushButton )应使用红色作为其前景色。
Qt 样式表通常不区分大小写(即color 、Color 、COLOR 和cOloR 指代的是同一属性)。唯一的例外是类名(object names )和 Qt 属性名,它们区分大小写。
可以为同一声明指定多个选择器,使用逗号(, )分隔这些选择器。例如,以下规则
QPushButton, QLineEdit, QComboBox { color: red }等同于以下三条规则的组合:
QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }样式规则的声明部分是由 property: value 成对项的列表,用大括号({} )括起,并以分号分隔。例如:
QPushButton { color: red; background-color: white }有关 Qt Widgets 提供的属性列表,请参阅下文的“属性列表”部分。
选择器类型
到目前为止,所有示例都使用了最简单的选择器类型——类型选择器。Qt 样式表支持CSS2 中定义的所有选择器。下表总结了最常用的选择器类型。
| 选择器 | 示例 | 说明 |
|---|---|---|
| 通用选择器 | * | 匹配所有控件。 |
| 类型选择器 | QPushButton | 匹配QPushButton 及其子类的实例。 |
| 属性选择器 | QPushButton[flat="false"] | 匹配非flat 的QPushButton 实例。您可以使用此选择器来检测任何支持QVariant::toString()的Qt属性(详情请参阅toString()函数的文档)。此外,还支持用于获取类名的特殊属性class 。该选择器也可用于检测动态属性。有关使用动态属性进行自定义的更多信息,请参阅“使用动态属性进行自定义”。 除了使用 ` 警告:如果在 设置样式表后 Qt 属性的值发生了变化,可能需要强制重新计算样式表。实现此目的的一种方法是先取消设置样式表,然后重新设置。 |
| 类选择器 | .QPushButton | 匹配QPushButton 的实例,但不匹配其子类的实例。 这等同于 ` |
| ID 选择器 | QPushButton#okButton | 匹配所有object name 为okButton 的QPushButton 实例。 |
| 后代选择器 | QDialog QPushButton | 匹配所有作为某个QDialog 的后代(子节点、孙节点等)的QPushButton 实例。 |
| 子节点选择器 | QDialog > QPushButton | 匹配所有作为QDialog 的直接子元素的QPushButton 实例。 |
子控件
要为复杂的小部件设置样式,必须访问该小部件的子控件,例如QComboBox 的下拉按钮或QSpinBox 的上下箭头。选择器可以包含子控件,从而能够将规则的应用范围限制在特定的小部件子控件上。例如:
QComboBox::drop-down { image: url(dropdown.png) }上述规则为所有QComboBox的下拉按钮设置样式。尽管双冒号(:: )语法与CSS3伪元素相似,但Qt子控件在概念上与这些伪元素不同,且具有不同的层叠语义。
子控件的位置总是相对于另一个元素——即参考元素——来确定的。该参考元素可以是小部件本身,也可以是另一个子控件。例如,QComboBox 的::drop-down默认位于QComboBox 的填充矩形右上角。 默认情况下,::drop-down位于::drop-down子控件的“内容”矩形中心。有关用于设置小部件样式及其默认位置的子控件,请参阅下方的“可样式化小部件列表”。
可通过subcontrol-origin属性更改要使用的原点矩形。例如,如果我们要将下拉菜单放置在QComboBox 的边距矩形中,而不是默认的内边距矩形中,可以指定:
下拉菜单在边距矩形内的对齐方式可通过 `subcontrol-position` 属性进行调整。
可使用width和height属性来控制子控件的大小。请注意,设置图片会隐式地设定子控件的大小。
相对定位方案(position: relative)允许子控件的位置相对于其初始位置发生偏移。例如,当点击QComboBox 的下拉按钮时,我们可能希望其中的箭头发生偏移,以呈现“被点击”的效果。要实现这一点,我们可以指定:
QComboBox::down-arrow {
image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
position: relative;
top: 1px; left: 1px;
}绝对定位方案(position: absolute)允许相对于参考元素来更改子控件的位置和大小。
定位完成后,它们将与小部件一样被处理,并可使用盒模型进行样式设置。
请参阅下方的“子控件列表”以了解受支持的子控件,并参阅《自定义 QPushButton 的菜单指示器子控件》以获取一个实际示例。
注意:对于 QComboBox 和QScrollBar 等复杂控件,如果自定义了一个属性或子控件,则必须同时自定义所有其他属性或子控件。
伪状态
选择器中可以包含伪状态,用于根据控件的状态限制规则的适用范围。伪状态位于选择器的末尾,中间用冒号 (:) 分隔。例如,当鼠标悬停在QPushButton 上时,以下规则将生效:
QPushButton:hover { color: white }QRadioButton可以使用感叹号运算符来否定伪状态。例如,当鼠标未悬停在 上时,以下规则生效:
QRadioButton:!hover { color: red }伪状态可以串联使用,此时默认采用逻辑“与”运算。例如,当鼠标悬停在已勾选的QCheckBox 上时,将应用以下规则:
QCheckBox:hover:checked { color: white }伪状态链中可能包含取反的伪状态。例如,当鼠标悬停在未被按下的QPushButton 上时,适用以下规则:
QPushButton:hover:!pressed { color: blue; }如有需要,可使用逗号运算符来表示逻辑或:
伪状态可以与子控件结合使用。例如:
QComboBox::drop-down:hover { image: url(dropdown_bright.png) }有关 Qt Widgets 提供的伪状态列表,请参阅下文的“伪状态列表”部分。
冲突解决
当多个样式规则为同一属性指定了不同的值时,就会产生冲突。请看以下样式表:
QPushButton#okButton { color: gray }
QPushButton { color: red }这两条规则都匹配名为okButton 的 `QPushButton ` 实例,且在 `color ` 属性上存在冲突。要解决此冲突,必须考虑选择器的特异性。在上例中,`QPushButton#okButton ` 被视为比 `QPushButton` 更具特异性,因为它(通常)指代单个对象,而非类的所有实例。
同样,包含伪状态的选择器比未指定伪状态的选择器更具特异性。因此,以下样式表规定,当鼠标悬停在QPushButton 上时,其文字应为白色;否则应为红色:
QPushButton:hover { color: white }
QPushButton { color: red }下面是一个比较棘手的情况:
QPushButton:hover { color: white }
QPushButton:enabled { color: red }在此,这两个选择器的特异性相同,因此当按钮处于激活状态时,如果鼠标悬停在其上方,第二条规则将具有优先级。如果我们希望在此情况下文本显示为白色,可以像这样重新排列规则的顺序:
QPushButton:enabled { color: red }
QPushButton:hover { color: white }或者,我们可以提高第一条规则的特异性:
QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }在类型选择器方面也存在类似的问题。请看以下示例:
QPushButton { color: red }
QAbstractButton { color: gray }这两条规则都适用于QPushButton 实例(因为QPushButton 继承了QAbstractButton ),因此color属性存在冲突。由于QPushButton 继承了QAbstractButton ,人们可能会误以为QPushButton 比QAbstractButton 更具体。然而,在样式表计算中,所有类型选择器的特异性都相同,最后出现的规则具有优先级。 换言之,所有 `QAbstractButton`(包括 `QPushButton`)的颜色都会被设置为 `gray `。如果我们真的希望 `QPushButton` 的文本显示为红色,可以随时重新排列规则的顺序。
在确定规则的特异性时,Qt样式表遵循CSS2规范:
选择器的特异性计算方法如下:
- 统计选择器中 ID 属性的数量(= a)
- 统计选择器中其他属性和伪类的数量(= b)
- 统计选择器中元素名的数量(= c)
- 忽略伪元素 [即子控件]。
将这三个数值 a-b-c 相加(采用大基数计数法)即可得到特异性。
一些示例:
* {} /* a=0 b=0 c=0 -> specificity = 0 */ LI {} /* a=0 b=0 c=1 -> specificity = 1 */ UL LI {} /* a=0 b=0 c=2 -> specificity = 2 */ UL OL+LI {} /* a=0 b=0 c=3 -> specificity = 3 */ H1 + *[REL=up]{} /* a=0 b=1 c=1 -> specificity = 11 */ UL OL LI.red {} /* a=0 b=1 c=3 -> specificity = 13 */ LI.red.level {} /* a=0 b=2 c=1 -> specificity = 21 */ #x34y {} /* a=1 b=0 c=0 -> specificity = 100 */
级联
样式表可设置在QApplication 、父级控件以及子级控件上。任意控件的实际样式表是通过合并其祖先(父级、祖父级等)上设置的样式表,以及QApplication 上设置的任何样式表而获得的。
当发生冲突时,无论冲突规则的特异性如何,小部件自身的样式表始终优先于任何继承的样式表。同样地,父级小部件的样式表优先于祖父级小部件的样式表,以此类推。
QApplication 由此产生的一个结果是:在小部件上设置一条样式规则,会自动使其优先于祖先小部件样式表或 `QApplication` 样式表中指定的其他规则。请看以下示例。首先,我们在 ` ` 上设置了一个样式表:
qApp->setStyleSheet("QPushButton { color: white }");然后,我们在QPushButton 对象上设置样式表:
myPushButton->setStyleSheet("* { color: blue }");QPushButton 上的样式表会强制QPushButton (及其任何子控件)的文本显示为蓝色,即使全局样式表中提供了更具体的规则也不例外。
如果我们写成
myPushButton->setStyleSheet("color: blue");,结果本应相同,只是如果QPushButton 有子控件(这种情况不太可能发生),该样式表将不会对其产生影响。
样式表的层叠机制是一个复杂的话题。有关详细信息,请参阅CSS2 规范。请注意,Qt XML 目前尚未实现!important 属性。
继承
在经典 CSS 中,当某项的字体和颜色未被显式设置时,它会自动从父项继承。默认情况下,使用 Qt 样式表时,小部件不会自动从其父小部件继承字体和颜色设置。
例如,考虑一个位于QGroupBox 内部的QPushButton :
qApp->setStyleSheet("QGroupBox { color: red; } ");该QPushButton 未显式设置颜色。因此,它不会继承其父控件QGroupBox 的颜色,而是采用系统默认颜色。如果我们要为QGroupBox 及其子控件设置颜色,可以这样编写:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");相比之下,使用 `QWidget::setFont()` 和 `QWidget::setPalette()` 设置字体和配色方案时,这些设置会传播到子控件。
如果您希望字体和调色板能传播到子控件,可以设置Qt::AA_UseStyleSheetPropagationInWidgetStyles 标志,如下所示:
用法:
QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);当启用小部件样式字体和配色方案的传播时,通过 Qt 样式表进行的字体和配色方案更改,其效果将等同于用户手动在样式表所针对的所有 Qt Widgets 上调用了相应的QWidget::setPalette() 和QWidget::setFont() 方法。
- 样式表所做的更改会进行传播。这些更改会在更改发生时,一次性推送到所有匹配该样式表的小部件上。
- 通过调用QWidget::setPalette() 或QWidget::setFont() 进行的更改具有继承性。所有现有及未来的子控件,只要未显式设置相应的画笔或字体,都会继承这些更改。
位于 C++ 命名空间内的控件
类型选择器可用于为特定类型的控件设置样式。例如,
classMyPushButton :publicQPushButton {
// ...
};
// ...
voidsomeFunction()
{
qApp->setStyleSheet("MyPushButton { background: yellow; }");
//...Qt 样式表使用小部件的 QObject::className() 来确定何时应用类型选择器。当自定义小部件位于命名空间内时,QObject::className() 会返回 <命名空间>::<类名>。这与子控件的语法存在冲突。 为解决此问题,当对命名空间内的控件使用类型选择器时,必须将:: 替换为-- 。例如,
namespacens {
classMyPushButton :publicQPushButton {
// ...
};
}
// ...
voidsomeMethod()
{
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");
//...设置 QObject 属性
从 4.3 及更高版本开始,任何可设计的Q_PROPERTY 都可以使用 qproperty-<属性名> 语法进行设置。
例如,
MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }如果该属性引用了使用Q_ENUM 声明的枚举,则应按名称引用其常量,而非其数值。
注意:请 谨慎使用 qproperty 语法,因为它会修改正在绘制的控件。此外,qproperty 语法仅在控件被样式修饰时评估一次。这意味着,在诸如QPushButton:hover 之类的伪状态中尝试使用它们是行不通的。
© 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.