目录
1. 基本语法
1.1 样式规则
QSS 由
样式规则
组成。以下是 3 条规则:
1.2 选择器、声明
样式规则 =
选择器
:声明
1.3 大小写
QSS 不区分大小写,但
类名
、
对象名
、
属性名
例外!假设有一个名为 objectName 的 QPushButton:
1.4 多个选择器
可以将多个选择器设置同一个声明,使用逗号
,
分割:
QPushButton, QLineEdit, QComboBox{color: red;}
等价于:
QPushButton{color: red;}QLineEdit{color: red;}QComboBox{color: red;}
2. 选择器
QSS 支持 CSS2 中定义的所有选择器。
2.1 通用选择器:*
匹配所有 widget。
2.2 类型选择器:QPushButton
匹配 QPushButton 及其子类。
2.3 属性选择器:QPushButton[flat=“false”]
匹配所有设置了 setFlat(false) 的 QPushButton。
使用该选择器既可以:1. 测试任何支持 QVariant::toString() 的 Qt 属性,还支持特殊的类属性,如类名;2. 还可以测试动态属性。
除了
=
,也可以使用
~=
来测试 QStringList 类型的 Qt 属性是否包含给定 QString。
注意:设置 qss 后,如果 Qt 属性值发生了变化,则需要强制重新计算 qss。方法是:重新设置 qss。
2.4 类选择器:.QPushButton
匹配 QPushButton,但不包括子类。等价于
*[class~="QPushButton"]
。
2.5 ID 选择器:QPushButton#okButton
匹配所有对象名为“okButton”的 QPushButton。
2.6 后代选择器:QDialog QPushButton
匹配作为 QDialog 的后代(直接子代、孙代)的 QPushButton。
2.7 直接子代选择器:QDialog > QPushButton
匹配作为 QDialog 的直接子级(即第一代)的 QPushButton。
3. 子控件
有些 widget 比较复杂,如 QComboBox 有下拉按钮、QSpinBox 有上下箭头,设置这些 widget 时可以指定子控件。
3.1 一个简单示例
例如:
QComboBox::drop-down{image:url(dropdown.png)}
3.2 子控件参考矩形
子控件始终相对于另一个元素定位。例如,QComboBox 的
::drop-down
默认放置在 QComboBox 的 Padding 矩形的右上角。
使用
subcontrol-origin
更改参考矩形。例如,想将下拉菜单放置在 QComboBox 的 “margin 矩形” 中而不是 “padding 矩形” 中,可以这样设置:
QComboBox{margin-right: 20px;}QComboBox::drop-down{subcontrol-origin: margin;}
3.3 子控件对齐方式
使用
subcontrol-position
更改 Margin 矩形中下拉菜单的对齐方式。
3.4 子控件大小
使用
width
和
height
可以设置子控件的大小。
注意:如果设置了
image
会默认设置子控件的大小。
3.5 子控件相对位置、绝对位置
使用
position: relative
设置相对定位,允许子控件偏离初始位置。
使用
position: absolute
设置绝对定位,允许子控件相对于参考元素更改位置。
一旦使用了
position
,子控件就被视为与 widget 相同,就可以使用盒模型设置。
注意:对于 QComboBox、QScrollBar 等复杂 widget,如果设置了某个属性、某个子控件,那么其他的属性、子控件也要设置。
4. 伪状态
伪状态是指 widget 的不同状态。
伪状态位于选择器的末尾,中间有一个冒号
:
。例如,鼠标悬浮按钮时:
QPushButton:hover{color: white }
使用感叹号
!
否定伪状态。例如,鼠标未悬浮按钮时:
QPushButton:!hover{color: red }
伪状态可以链接,此时默认隐含逻辑与。例如,鼠标悬停在选中的 QCheckBox 上时:
QCheckBox:hover:checked{color: white }
可以使用逗号
,
表示逻辑 OR:
QCheckBox:hover, QCheckBox:checked{color: white }
伪状态可以与子控件一起出现。 例如:
QComboBox::drop-down:hover{image:url(dropdown_bright.png)}
5. 解决冲突
5.1 产生冲突的原因
如果匹配到同一个 widget 的同一个属性但却设置了不同值,就会产生冲突。例如:
QPushButton#okButton{color: gray }QPushButton{color: red }
两个规则都能匹配名为 okButton 的 QPushButton,但是设置了不同的文本色,这时就需要考虑
选择器的优先级
。
5.2 解决冲突方法1:更具体的选择器
例如:
- QPushButton#okButton 比 QPushButton 优先级更高,因为它(通常)指的是单个对象,而不是类的所有实例。
- 具有伪状态的选择器比不指定伪状态的选择器优先级更高。例如:
QPushButton:hover{color: white }QPushButton{color: red }
当鼠标悬停在 QPushButton 上时文本为白色,否则为红色。
这是一个棘手的问题:
5.3 解决冲突方法2:相同优先级的选择器,位于下方的优先级高
一个示例,两个选择器优先级相同,但由于
enable
位于
hover
下方,因此优先级更高:
QPushButton:hover{color: white }QPushButton:enabled{color: red }
另一个示例:
QPushButton{color: red }QAbstractButton{color: gray }
虽然 QPushButton 是 QAbstractButton 的子类,似乎
更具体
,但对于样式表计算,所有类型选择器都具有相同的特性,并且最后出现的规则优先。因此,所有按钮颜色都设置为灰色,包括 QPushButtons。
5.4 优先级计算
Qt Style Sheet 遵循 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 */
6. 级联(Cascading)
widget 的 qss 继承
父widget
。如果 widget 设置了自己的 qss,则优先级高于继承的 qss。
例如:
qApp->setStyleSheet("QPushButton { color: white }");
myPushButton->setStyleSheet("* { color: blue }");
最终按钮的文本色为蓝色。
级联是一个很复杂的话题,请参阅 CSS2 Specification。
注意:Qt 没有实现!imporant
。
7. 继承
7.1 CSS 中的继承
在经典 CSS 中,字体和颜色会自动从父项继承。
7.2 QSS 中的继承
注意:Qt Style Sheet 中的 widget 不会自动从其父部件继承字体和颜色
例如,QGroupBox 中有个 QPushButton。QPushButton 不会自动继承 QGroupBox 的颜色,而是使用系统颜色:
qApp->setStyleSheet("QGroupBox { color: red; } ");
如果想为 QGroupBox 及其子对象设置颜色,可以这样写:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
使用
QWidget::setFont()
和
QWidget::setPalette()
设置字体和调色板会传播到子部件。
如果您希望字体和调色板传播到子小部件,可以设置
Qt::AA_UseStyleSheetPropagationInWidgetStyles
标志,如下所示:
QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles,true);
当启用该功能时,通过 QSS 设置的字体和调色板变化时,其行为类似于调用
QWidget::setPalette()
和
QWidget::setFont()
。如果所调函数能在 C++ 中传播,则也就可以在 qss 中传播。
8. 命名空间中的 widget
类型选择器可用于为特定类型的 widget 设置样式。例如:
classMyPushButton:publicQPushButton{// ...}
qApp->setStyleSheet("MyPushButton { background: yellow; }");
Qt Style Sheet 使用 widget 的
QObject::className()
来确定何时应用类型选择器。当自定义部件在命名空间内时,QObject::className() 返回 ::,
这与子控件的语法冲突
。为了克服这个问题,在命名空间内使用类型选择器时,我们必须将“
::
”替换为“
--
”。 例如:
namespace ns {classMyPushButton:publicQPushButton{// ...}}
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");
9. 设置 QObject 属性
从 Qt 4.3 开始,可以使用
qproperty-<property name>
语法设置 Q_PROPERTY,例如:
MyLabel{qproperty-pixmap:url(pixmap.png);}MyGroupBox{qproperty-titleColor:rgb(100, 200, 100);}QPushButton{qproperty-iconSize: 20px 20px;}
如果该属性引用了一个用 Q_ENUMS 声明的枚举,您应该按名称引用它的常量,即,而不是它们的数值。
注意:请谨用 qproperty 语法,因为它会修改正在绘制的小部件。此外,qproperty 语法只评估一次,即当小部件被样式修饰时。这意味着在 QPushButton:hover 等伪状态下使用它们的任何尝试都将不起作用。
版权归原作者 南理汉子 所有, 如有侵权,请联系我们删除。