目录
QSS 由样式规则组成。以下是 3 条规则:

样式规则 = 选择器+声明:

QSS 不区分大小写,但类名、对象名、属性名例外!假设有一个名为 objectName 的 QPushButton:

可以将多个选择器设置同一个声明,使用逗号,分割:
QPushButton, QLineEdit, QComboBox { color: red; }
等价于:
QPushButton { color: red; }
QLineEdit { color: red; }
QComboBox { color: red; }
QSS 支持 CSS2 中定义的所有选择器。
匹配所有 widget。
匹配 QPushButton 及其子类。
匹配所有设置了 setFlat(false) 的 QPushButton。
使用该选择器既可以:1. 测试任何支持 QVariant::toString() 的 Qt 属性,还支持特殊的类属性,如类名;2. 还可以测试动态属性。
除了=,也可以使用~=来测试 QStringList 类型的 Qt 属性是否包含给定 QString。
注意:设置 qss 后,如果 Qt 属性值发生了变化,则需要强制重新计算 qss。方法是:重新设置 qss。
匹配 QPushButton,但不包括子类。等价于 *[class~="QPushButton"]。
匹配所有对象名为“okButton”的 QPushButton。
匹配作为 QDialog 的后代(直接子代、孙代)的 QPushButton。

匹配作为 QDialog 的直接子级(即第一代)的 QPushButton。

有些 widget 比较复杂,如 QComboBox 有下拉按钮、QSpinBox 有上下箭头,设置这些 widget 时可以指定子控件。
例如:
QComboBox::drop-down { image: url(dropdown.png) }

子控件始终相对于另一个元素定位。例如,QComboBox 的 ::drop-down 默认放置在 QComboBox 的 Padding 矩形的右上角。
使用 subcontrol-origin 更改参考矩形。例如,想将下拉菜单放置在 QComboBox 的 “margin 矩形” 中而不是 “padding 矩形” 中,可以这样设置:
QComboBox {
margin-right: 20px;
}
QComboBox::drop-down {
subcontrol-origin: margin;
}

使用 subcontrol-position 更改 Margin 矩形中下拉菜单的对齐方式。
使用 width 和 height 可以设置子控件的大小。
注意:如果设置了
image会默认设置子控件的大小。
使用 position: relative 设置相对定位,允许子控件偏离初始位置。
使用 position: absolute 设置绝对定位,允许子控件相对于参考元素更改位置。
一旦使用了 position,子控件就被视为与 widget 相同,就可以使用盒模型设置。
注意:对于 QComboBox、QScrollBar 等复杂 widget,如果设置了某个属性、某个子控件,那么其他的属性、子控件也要设置。
伪状态是指 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) }
如果匹配到同一个 widget 的同一个属性但却设置了不同值,就会产生冲突。例如:
QPushButton#okButton { color: gray }
QPushButton { color: red }
两个规则都能匹配名为 okButton 的 QPushButton,但是设置了不同的文本色,这时就需要考虑 选择器的优先级。
例如:
QPushButton:hover { color: white }
QPushButton { color: red }
当鼠标悬停在 QPushButton 上时文本为白色,否则为红色。
这是一个棘手的问题:
一个示例,两个选择器优先级相同,但由于 enable 位于 hover 下方,因此优先级更高:
QPushButton:hover { color: white }
QPushButton:enabled { color: red }
另一个示例:
QPushButton { color: red }
QAbstractButton { color: gray }
虽然 QPushButton 是 QAbstractButton 的子类,似乎更具体,但对于样式表计算,所有类型选择器都具有相同的特性,并且最后出现的规则优先。因此,所有按钮颜色都设置为灰色,包括 QPushButtons。
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 */
widget 的 qss 继承 父widget。如果 widget 设置了自己的 qss,则优先级高于继承的 qss。
例如:
qApp->setStyleSheet("QPushButton { color: white }");
myPushButton->setStyleSheet("* { color: blue }");
最终按钮的文本色为蓝色。
级联是一个很复杂的话题,请参阅 CSS2 Specification。
注意:Qt 没有实现!imporant。
在经典 CSS 中,字体和颜色会自动从父项继承。
注意: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 中传播。
类型选择器可用于为特定类型的 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; }");
从 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 等伪状态下使用它们的任何尝试都将不起作用。
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a
可能已经问过了,但我找不到它。这里有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
我正在学习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
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new
在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个: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
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
方法应返回-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(