Qss样式表语法 原创
QSS样式表语法
更多精彩内容 |
---|
👉个人内容分类汇总 👈 |
👉QSS样式学习 👈 |
概述
- Qt样式表的概念,术语和语法在很大程度上受到HTML层叠样式表 (CSS)的启发,Qt样式表遵循CSS2规范;
- 如果Qt样式表与设置小部件外观的函数(如QWidget::setFont() 或QTreeWidgetItem::setBackground() )用于同一小部件,则如果设置冲突,样式表将优先;
- 使用QApplication::setStyleSheet()在整个应用程序上设置;
- 使用QWidget::setStyleSheet()在特定小部件(及其子组件)上设置。
一、样式规则
样式表由一系列样式规则组成。样式规则由选择器和以及一条或多条声明组成。
- 选择器: 指定哪些小部件受规则影响;
- 声明: 指定应在小组件上设置哪些属性,每条声明由一个属性和一个值组成,声明总是以分号 ; 结束,声明总以大括号 {} 括起来。
例如:
Qt 样式表通常不区分大小写,例如:color、Color、COLOR;但是类名、对象名、 Qt 属性名区分大小写。
可以为同一声明指定多个选择器,使用逗号 分隔选择器。例如:
QPushButton, QLineEdit, QComboBox { color: red }
/* 上面的语法等效于 */
QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }
二、选择器类型
Qt样式表支持CSS2中定义的所有选择器。
-
通用选择器
- 示例:
*
; - 解释:匹配所有控件。
- 示例:
-
类型选择器
- 示例:
QPushButton
,控件类型; - 解释:匹配 QPushButton 及其子类的实例。
- 示例:
-
属性选择器
-
示例:
QPushButton[flat="false"]
-
解释:匹配 QPushButton 属性flat为false的实例,属性选择器还可以用于动态属性设置。
-
-
类选择器
- 示例:
.QPushButton
,注意比类型选择器前面多了一个点; - 解释:匹配 QPushButton 的实例,但不匹配其子类的实例。这相当于 。
*[class~="QPushButton"]
- 示例:
-
ID选择器
- 示例:
QPushButton#okButton 或 #okButton
; - 解释:匹配对象名称为.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 的填充矩形的右上角。
可以使用子控件矩形原点属性更改要使用的源矩形。例如,如果我们想将下拉列表放在 QComboBox 的边距矩形而不是默认的填充矩形中,我们可以指定:
QComboBox {
margin-right: 20px;
}
QComboBox::drop-down {
subcontrol-origin: margin; /* 子控件矩形起点 */
}
四、伪状态
选择器可能包含伪状态,这些伪状态表示根据小组件的状态限制规则的应用。伪状态显示在选择器的末尾,中间有一个冒号:
。例如,当鼠标悬停在 QPushButton 上时可以使用:
QPushButton:hover { color: white }
可以使用感叹号运算符对伪状态进行求反。例如,当鼠标未悬停在 QRadioButton 上时可以使用:
QRadioButton:!hover { color: red }
伪状态支持链接(没有先后),在这种情况下,逻辑 AND 是隐含的。例如,当鼠标悬停在选中的 QCheckBox 上时可以使用:
QCheckBox:hover:checked { color: white }
伪状态取反可以出现再伪状态链中,例如:
QPushButton:hover:!pressed { color: blue; }
如果需要,可以使用逗号运算符表示逻辑 或(OR):
QCheckBox:hover, QCheckBox:checked { color: white }
伪状态可以与子控件组合出现。例如:
QComboBox::drop-down:hover { image: url(dropdown_bright.png) }
五、样式表冲突解决
当多个样式规则将同一属性指定不同的值时,就会发生冲突,例如:
QPushButton#okButton { color: gray }
QPushButton { color: red }
两个样式规则都设置了QPushButton的color值,属性存在冲突,为了解决这种冲突,我们必须考虑选择器的特殊性,QPushButton#okButton
比QPushButton
更具体。
同样,具有伪状态的选择器比不指定伪状态的选择器更具体。因此,以下样式表指定当鼠标悬停在 QPushButton 上时,QPushButton 应具有白色文本,否则为红色文本:
QPushButton:hover { color: white }
QPushButton { color: red }
- 所以:更具体的优先级更高。
如果两条规则同样具体,则排在后面的优先级更高,如果hover放在前面,则当鼠标悬停再QPushButton上时样式表不会生效;
QPushButton:hover{
border: 2px solid #8f8f91; /* 设置边框粗细、样式、颜色*/
border-radius: 6px; /* 设置边框圆角 */
background-color: rgb(0, 255, 0);
}
QPushButton:enabled {
border: 2px solid #8f8f91; /* 设置边框粗细、样式、颜色*/
border-radius: 6px; /* 设置边框圆角 */
background-color: rgb(255, 0, 0);
}
可以通过使第一条规则更具体解决第一天规则不生效的问题:
QPushButton:hover:enabled{
border: 2px solid #8f8f91; /* 设置边框粗细、样式、颜色*/
border-radius: 6px; /* 设置边框圆角 */
background-color: rgb(0, 255, 0);
}
QPushButton:enabled {
border: 2px solid #8f8f91; /* 设置边框粗细、样式、颜色*/
border-radius: 6px; /* 设置边框圆角 */
background-color: rgb(255, 0, 0);
}
如果都是使用类型选择器,如下列这种情况,则也是排在后面的优先级更高。
QPushButton { color: red }
QAbstractButton { color: gray }
为了确定规则的特殊性,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有子项(这不太可能),样式表对它们没有影响。
七、继承
在经典 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 样式表进行的字体和调色板更改的行为就像用户在样式表针对的所有 QWidget 上手动调用了相应的 QWidge::setPalette() 和 QWidget::setFont() 方法一样。如果这会导致在C++中传播,则会导致样式表中的传播,反之亦然。
八、命名空间中的控件
Qt 样式表使用小部件的 QObject::className() 来确定何时应用类型选择器。
当自定义小部件位于命名空间内时,QObject::className() 返回<namespace>::<classname>
。这与子控件的语法冲突。
为了克服这个问题,当对命名空间中的小部件使用类型选择器时,我们必须将::
替换为--
。例如:
namespace ns {
class MyPushButton : public QPushButton {
// ...
}
}
// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");