Qt样式表简介
QSS样式表允许用户定制widgets组件外观,与前端CSS语法类似。子类化QStyle也可以定制widgets组件外观。
QT样式表编程
- 通过文件设置QSS
将QSS代码写入.qss 文件,将.qss 文件加入资源文件qrc.qrc中,在代码中读取QSS文件设置组件QSS
QFile file(":/qss/test.qss");
file.open(QIODevice::ReadOnly);
QString styleshoot = QLatinlString(file.readAll());
this->setStyleSheet(stylesheet);
file.close();
Qt样式表语法
Qt样式表的术语和语法规则与HTML CSS很相似。
- 样式规则
样式表由样式规则序列组成。样式规则由选择器和声明组成。选择器指定了哪些组件受规则影响,声明指定了组件设置哪些属性。
QWidget {
color: red;
}
该样式规则中,QWidget是选择器,{ color: red } 是声明。样式规则指及其子类应使用红色作为前景色。
QT样式表大小写不敏感,除了类名,对象名,QT属性名是大小写敏感的多个选择器可以指定同一个声明,使用逗号分隔选择器。
如:
QPushButton, QLineEdit, QComboBox {
color: red
}
等效于以下:
QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }
样式规则的声明部分是一个"属性: 值"对的链表. 声明部分在{}内,不同的属性: 值“对使用分号分隔。 例如:
QPushButton {
color: red;
background-color: white;
}
- 选择器的类型
QT样式表支持CSS2定义的所有选择器。
选择器 | 示例 | 说明 |
---|---|---|
通用选择器 | * | 匹配所有组件 |
类型选择器 | QPushButton | 匹配所有QPushButton机器子类的实例 |
属性选择器 | QPushButton[flat=“false”] | 匹配所有QPushButton的属性flat为false的实例。属性分为静态属性和动态属性,静态属性可以通过Q_PROPERTY()来指定,动态属性可以使用ssetProperty来指定。 |
类选择器 | .PushButton | 匹配QPushButton的实例,子类除外 |
ID选择器 | QPushButton#okButton | 匹配对象名为okButton的所有QPushButton实例 |
后代选择器 | QDialog QPushButton | 匹配QDialog后代的所有QpushButton实例 |
子选择器 | QDialog > QpushButton | 匹配QDialog子类对象QPushButton的所有实例 |
- 子控件选择器
对于样式复杂的组件,需要访问组件的子控件,如QComboBox的下拉按钮或QSpinBox的上下箭头。选择器可以包含子控件来对组件的特定子控件应用规则。
QComboBox::drop-down
{
p_w_picpath: url(dropdown.png);
}
以上规则会对所有QComboBox的下拉框应用样式规则。尽管双冒号::很像CSS3的伪元素,但QT子控件选择器在概念上是不同的,有不同的级联语义。
子控件选择器通常根据另外一个参考元素进行定位。参考元素可以是组件或是另一个子控件选择器。例如:QComboBox的::drop-down 默认放置在QComboBox衬底矩形的右上角。::drop-down默认放置在::drop-down子控件选择器的内容矩形的中心.
可以使用subcontrol-origin属性改变原点矩形。例如,如果想要将drop-down放置在边界矩形而不是默认的衬底矩形,可以指定:
QComboBox {
margin-right: 20px;
}
QComboBox::drop-down {
subcontrol-origin: margin;
}
drop-down在边界矩形内的对齐方式通过subcontrol-position 属性改变。 宽属性和高属性用于控制子控件选择器的大小。注意,设置一幅图片会隐式地设置子控件选择器的大小。
相对定位方法(position: relative)允许子控件选择器的位置偏离它原来的位置。例如,当QComboBox的下拉按钮按下,想要一种被按下的效果可以通过指定如下实现:
QComboBox::down-arrow {
p_w_picpath: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
position: relative;
top: 1px; left: 1px;
}
绝对定位方法(position: absolute)允许子控件选择器的位置和大小的改变与参考元素有关。一旦定位,就可以像组件那样使用盒子模型对其进行造型。
注意: 像QComboBox和QScrollBar这样复杂的组件,如果有一个属性或是子控件选择器被定制,所有其他的属性或是子控件选择器也要必须被定制。
常用辅助控制器:
控制器 | 功能 |
---|---|
::indicator | 单选框,复选框,可选菜单项或可选组件的指示器 |
::menu-indicator | 按钮的菜单指示器 |
::item | 菜单,菜单栏或状态栏项 |
::up-button | 微调框或滚动条的向下按钮 |
::down-button | 微调框或滚动条的向下按钮 |
::up-arrow | 微调框,滚动条或标题视图的向上按钮 |
::down-arrow | 微调框,滚动条或标题视图的向下按钮 |
::drop-down | 组合框的下拉箭头 |
::title | 群组框的标题 |
- 伪选择器
选择器可能包含限制基于组件化状态的规则应用的伪状态。伪状态出现在选择器的尾部,中间使用分号连接。例如,以下规则用于鼠标悬停在一个QPushButton上:
QPushButton:hover {
color: white;
}
伪状态可以使用感叹号取反,例如,以下规则用于鼠标不悬停在QPushButton:
QPushButton:!hover {
color: red;
}
伪状态可以以逻辑与的方式连接使用,例如,以下规则应用于鼠标悬停在一个选中的QCheckBox上:
QCheckBox:hover:checked {
color: white;
}
取反伪状态可以出现在伪状态链中。例如,以下规则用于鼠标悬停在一个QPushButton上,但没有按下:
QPushButton:hover:!pressed {
color: white;
}
如果需要,使用逗号可以将伪状态以逻辑或连接。
QCheckBox:hover, QCheckBox:checked {
color: white;
}
伪状态可以结合子控件选择器使用:
QComboBox:drop-down:hover {
p_w_picpath: url(dropdown_bright.png)
}
常用状态:
状态 | 功能 |
---|---|
:disabled | 禁用的窗口部件 |
:enabled | 启用的窗口部件 |
:focus | 窗口部件有输入焦点 |
:hover | 鼠标在窗口部件上悬停 |
:pressed | 鼠标按键点击窗口部件 |
:checked | 按钮未被选中 |
:unchecked | 按钮被部分选中 |
:indeterminate | 按钮被部分选中 |
:open | 窗口部件处于打开或扩展的状态 |
:closed | 窗口部件处于关闭或销毁状态 |
:on | 窗口部件的状态是on |
:off | 窗口部件的状态是off |
属性选择器
test.qss
QWidget#CertifucateButtonImage {
image: url(:/image/png/certificate_white.png);
min-width: 80px;
min-height: 80px;
max-width: 128px;
max-height: 128px;
}
QWidget#CertifucateButtonImage[State="hover"] {
image: url(:/image/png/certificate_blue.png);
min-width: 80px;
min-height: 80px;
max-width: 128px;
max-height: 128px;
}
QWidget#CertifucateButtonImage[State="checked"] {
image: url(:/image/png/certificate_blue.png);
min-width: 80px;
min-height: 80px;
max-width: 128px;
max-height: 128px;
}
C++
// 设置属性状态
m_pRootWidget->setProperty("State", state);
// 重新设置属性
m_pRootWidget->setStyle(QApplication::style());
- 冲突处理
当多个样式规则使用多个值指定同一个属性时会产生冲突。
QPushButton#Test { color: gray; }
QPushButton { color: red; }
以上两条规则匹配名为Test的QPushButton实例,在color属性上有冲突。为了解决冲突,需要考虑选择器的特征。上例中,QPushButton#Test比QPushButton要更具体,因为QPushButton#Test指向单个的对象,而不是类的所有实例。
类似,伪选择器比指定伪状态的选择器更具体。因而,以下样式表指定,当鼠标悬停在QPushButton上时,QPushButton的文本为白色,否则为红色。
为了确定规则的特性,Qt样式表遵循CSS2规范:
选择器特性的计算方法如下:
-
计算选择器中ID属性的数量(=a)
-
计算选择器中其他属性和伪状态类的数量(=b)
-
计算选择器中元素的数量(=c)
-
忽略伪元素(如子控件选择器)
-
级联
QT样式表可以设置在应用程序,父组件,子组件上。通过合并组件的祖先(父亲,祖父等)可以获取任意组件的有效样式表,以及设置在应用程序上的任何样式表。
冲突发生时,不论冲突规则的特性如何,组件自己的样式表总是优先于任何继承而来的样式表。同样,父组件的样式表优先于祖父组件的样式表。
这样的结果是,在一个组件上设置样式规则会自动获得比祖先组件的样式表或是应用程序的样式表指定的其他规则更高的优先级。例如,首先在应用程序设置样式表:
this->setStyleSheet("QPushButton{ color: white; }");
然后,在QPushButton对象设置一个样式表
this->setStyleSheet("*{ color: blue; }");
QPushButton的样式表会强制QPushButton(及其任何子组件)显示蓝色文本,尽管应用程序范围的样式表提供了更具体的规则。
但如果QPushButton有子组件,样式表不会对子组件有效果。
样式表级联是一个复杂的主题,更详细的内容请参考CSS2规范。QT目前没有实现。
- 继承
在经典的CSS中,当元素的字体和颜色没有显示设置时,会自动从父组件继承。使用QT样式表时,一个组件不会自动继承父组件设置的字体和颜色。例如,一个QGroupBox包含一个QPushButton:
this->setStyleSheet("QGroupBox{ color: red; }");
QPushButton并没有显示设置颜色,因此并不是继承父组件QGroupBox的颜色,而是拥有系统的颜色。如果要设置QGroupBox及其子组件的颜色,如下:
this->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
- C++命名空间内部的组件
类型选择器特殊的组件的样式定制。
class MyPushButton : public QPushButton
{
};
this->setStyleSheet("MyPushButton { background: yellow; }");
Qt样式表使用组件的QObject::className() 确定何时应选择器。当自定义组件在命名空间内部时,QObject::className() 会返回::.这会与子控件选择器的语法产生冲突。为了解决这个问题,当在命名控件内使用组件的类型选择器时,必须使用"–“代替”::".
namespace ns {
class MyPushButton : public QPushButton
{
};
}
this->setStyleSheet("ns--MyPushButton{ background: yellow; }");
- 设置QObject属性
从Qt4.3开始,任何可被设计的Q_PROPERTY都可以使用qproperty- 语法设置。
MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }
如果属性引用了Q_ENUMS声明的枚举,应该通过名字引用常量值,而不是数字。
- 盒子模型