jjzjj

QSS 语法

南理汉子 2023-11-12 原文

目录


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 子控件大小

使用 widthheight 可以设置子控件的大小。

注意:如果设置了 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 规范

优先级计算规则:

  1. 计算选择器中 ID 属性的数量 a;
  2. 计算选择器中其他属性和伪类的数量 b;
  3. 计算选择器中元素名的数量 c;
  4. 忽略伪元素,如子控件;
  5. 最后,连接 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 设置样式。例如:

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

Qt Style Sheet 使用 widget 的 QObject::className() 来确定何时应用类型选择器。当自定义部件在命名空间内时,QObject::className() 返回 ::,这与子控件的语法冲突。为了克服这个问题,在命名空间内使用类型选择器时,我们必须将“::”替换为“--”。 例如:

namespace ns {
    class MyPushButton : public QPushButton {
        // ...
    }
}
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 等伪状态下使用它们的任何尝试都将不起作用。

有关QSS 语法的更多相关文章

  1. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  2. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  3. ruby - 覆盖相似的方法,更短的语法 - 2

    在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a

  4. ruby 语法糖 : dealing with nils - 2

    可能已经问过了,但我找不到它。这里有2个常见的情况(对我来说,在编程Rails时......)用ruby​​编写是令人沮丧的:"astring".match(/abc(.+)abc/)[1]在这种情况下,我得到一个错误,因为字符串不匹配,因此在nil上调用[]运算符。我想找到的是比以下内容更好的替代方法:temp="astring".match(/abc(.+)abc/);temp.nil??nil:temp[1]简而言之,如果不匹配,则简单地返回nil而不会出错第二种情况是这样的:var=something.very.long.and.tedious.to.writevar=some

  5. ruby - Ruby 语法糖有 "rules"吗? - 2

    我正在学习Ruby的基础知识(刚刚开始),我遇到了Hash.[]method.它被引入a=["foo",1,"bar",2]=>["foo",1,"bar",2]Hash[*a]=>{"foo"=>1,"bar"=>2}稍加思索,我发现Hash[*a]等同于Hash.[](*a)或Hash.[]*一个。我的问题是为什么会这样。是什么让您将*a放在方括号内,是否有某种规则可以在何时何地使用“it”?编辑:我的措辞似乎造成了一些困惑。我不是在问数组扩展。我明白了。我的问题基本上是:如果[]是方法名称,为什么可以将参数放在括号内?这看起来几乎——但不完全是——就像说如果你有一个方法Foo.d

  6. ruby - 如何让Ruby捕获线程中的语法错误 - 2

    我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

  7. ruby -::在 Ruby 语法中是什么意思? - 2

    这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new

  8. ruby - ruby 乘法语句中星号中断语法前的空格 - 2

    在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个:classCdefx42endendm=C.new现在这将给出“错误数量的参数”:m.x*m.x这将给出“语法错误,意外的tSTAR,期待$end”:2/m.x*m.x这里的解析器到底发生了什么?我使用Ruby1.9.2和2.1.5进行了测试。 最佳答案 *用于运算符(42*42)和参数解包(myfun*[42,42])。当你这样做时:m.x*m.x2/m.x*m.xRuby将此解释为参数解包,而不是*运算符(即乘法)。如果您不熟悉它,参数解包(有时也称为“spl

  9. 语法类似于 GitHub Flavored Markdown 的 Ruby markdown 解释器? - 2

    我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong

  10. ruby - 是否有用于复杂比较的漂亮语法? - 2

    方法应返回-1,0或1分别表示“小于”、“等于”和“大于”。对于某些类型的可排序对象,通常将排序顺序基于多个属性。以下是可行的,但我认为它看起来很笨拙:classLeagueStatsattr_accessor:points,:goal_diffdefinitializepts,gd@points=pts@goal_diff=gdenddefothercompare_pts=pointsother.pointsreturncompare_ptsunlesscompare_pts==0goal_diffother.goal_diffendend尝试一下:[LeagueStats.new(

随机推荐