Qt样式表官方文档(二)——语法

目录

声明

样式规则

选择器类型

子控件

伪状态

冲突解决

级联

继承

C++命名空间中的小部件

设置QObject属性


声明

本文是对Qt的Style Sheets官方文档的翻译,链接是The Style Sheet Syntax

Qt样式表术语和语法规则几乎与HTML CSS相同。如果您已经了解CSS,您可能可以快速浏览本节。

样式规则

样式表由一系列样式规则组成。样式规则由选择器和声明组成。选择器指定受规则影响的控件;声明指定应该在控件上设置哪些属性。例如:

QPushButton { color: red }

在上面的样式规则中,QPushButton是选择器,{color: red}是声明。该规则指定QPushButton和它的子类(例如,MyPushButton)应该使用红色作为它们的前景色。

Qt样式表通常是不区分大小写的(即color, color, color和color指的是同一个属性)。唯一的例外是类名、对象名和Qt属性名,它们是区分大小写的。

可以为同一声明指定多个选择器,使用逗号(,)分隔选择器例如,规则

QPushButton, QLineEdit, QComboBox { color: red }

相当于以下三条规则:

QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }

样式规则的声明部分是一个属性值对列表,用大括号({})括起来,并用分号分隔。例如:

QPushButton { color: red; background-color: white }

有关Qt控件提供的属性列表,请参阅属性列表部分。

选择器类型

到目前为止的所有示例都使用了最简单的选择器类型,即type selector。Qt样式表支持CSS2中定义的所有选择器。下表总结了最有用的选择器类型。

选择器示例解释
通用选择器*匹配所有控件
类型选择器QPushButton匹配QPushButton及其子类的实例
属性选择器QPushButton[flat="false"]

匹配非平面的QPushButton实例。您可以使用此选择器来测试支持QVariant::toString()的任何Qt属性(详细信息请参阅toString()函数文档)。此外,还支持特殊的class属性,用于类的名称。


此选择器也可用于测试动态属性。有关使用动态属性自定义的详细信息,请参阅使用动态属性自定义。

除了=之外,你还可以使用~=来测试QStringList类型的Qt属性是否包含给定的QString。

警告:如果Qt属性的值在样式表设置后发生变化,可能需要强制样式表重新计算。实现这一点的一种方法是取消对样式表的设置,然后重新设置。

类选择器.QPushButton匹配QPushButton的实例,但不匹配它的子类。
这相当于*[class~="QPushButton"]。
ID选择器QPushButton#okButton匹配对象名称为okButton的所有QPushButton实例
后代选择器QDialog QPushButton匹配QPushButton的所有实例,这些实例是QDialog的后代(子、孙子等)
子选择器QDialog > QPushButton匹配QPushButton的所有实例,它们是QDialog的直接子类。

子控件

对于样式化复杂的小部件,有必要访问小部件的子控件,例如QComboBox的下拉按钮或QSpinBox的上下箭头。选择器可能包含子控件,从而可以将规则的应用限制到特定的小部件子控件例如:

QComboBox::drop-down { image: url(dropdown.png) }

上面的规则样式化了所有QComboBox的下拉按钮。尽管双冒号(::)语法让人想起CSS3的伪元素,Qt子控件在概念上与它们不同,并且具有不同的级联语义。

子控件总是相对于另一个元素——参考元素——进行定位。这个参考元素可以是小部件或另一个子控件。例如,QComboBox的::drop-down默认放置在QComboBox的Padding矩形的右上角。默认情况下,下拉框被放置在下拉子控件的Contents矩形的中央。请参阅下面可设置样式的小部件列表,了解用于可设置样式的小部件及其默认位置的子控件。

可以使用subcontrol-origin属性更改要使用的原点矩形。例如,如果我们想将下拉框放置在QComboBox的边距矩形中,而不是默认的填充矩形中,我们可以指定:

QComboBox {
    margin-right: 20px;
}
QComboBox::drop-down {
    subcontrol-origin: margin;
}

使用subcontrol-position属性更改边距矩形内下拉框的对齐方式。

宽度和高度属性可用于控制子控件的大小。注意,设置图像会隐式地设置子控件的大小。

相对定位方案(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; }

如果需要,可以使用逗号操作符表示逻辑或:

QCheckBox:hover, QCheckBox:checked { color: white }

伪状态可以与子控件一起出现。例如:

QComboBox::drop-down:hover { image: url(dropdown_bright.png) }

请参阅下面的伪状态列表部分,了解Qt小部件提供的伪状态列表。

冲突解决

当几个样式规则用不同的值指定相同的属性时,就会出现冲突考虑下面的样式表:

QPushButton#okButton { color: gray }
QPushButton { color: red }

这两个规则都匹配名为okButton的QPushButton实例,并且颜色属性存在冲突。为了解决这个冲突,我们必须考虑选择器的特殊性在上面的例子中,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),并且颜色属性存在冲突。因为QPushButton继承了QAbstractButton,所以很容易认为QPushButton比QAbstractButton更具体。但是,对于样式表计算,所有类型选择器都具有相同的专一性,最后出现的规则优先换句话说,所有QAbstractButtons(包括QPushButtons)的颜色都设置为灰色。如果我们真的想要QPushButtons有红色文本,我们总是可以重新排序规则。

为了确定规则的特异性,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目前还没有实现!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样式表进行的字体和调色板更改将表现为用户在样式表所针对的所有QWidgets上手动调用相应的QWidget::setPalette()和QWidget::setFont()方法。

  • 样式表所做的更改将被传播。在进行更改时,将它们一次性推送到与样式表匹配的所有小部件。
  • 通过调用QWidget::setPalette()或QWidget::setFont()所做的更改将被继承。它们由所有现有和未来的子节点继承,其中相应的笔刷或字体尚未显式设置。

C++命名空间中的小部件

类型选择器可用于为特定类型的小部件设置样式。例如,

class MyPushButton : public QPushButton {
    // ...
}

// ...
qApp->setStyleSheet("MyPushButton { background: yellow; }");

Qt样式表使用小部件的QObject::className()来确定何时应用类型选择器。当自定义小部件位于名称空间中时,QObject::className()返回<namespace>::<className>。这与子控件的语法冲突。为了克服这个问题,在名称空间内为小部件使用类型选择器时,必须用--替换::。例如,

namespace ns {
    class MyPushButton : public QPushButton {
        // ...
    }
}

// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");

设置QObject属性

从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_ENUM声明的枚举,则应该通过名称引用其常量,而不是它们的数值。

注意:要小心使用qproperty语法,因为它会修改正在绘制的小部件。此外,qproperty语法只求值一次,即在小部件被样式修饰时。这意味着在伪状态(如QPushButton:hover)中使用它们的任何尝试都将不起作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值