目录
0.前言1.基本语法2.QSS设置方式1.指定控件样式设置2.全局样式设置3.从文件加载样式表4.使⽤Qt Designer编辑样式5.总结 3.选择器1.选择器概况2.子控件选择器3.伪类选择器
0.前言
Qt仿照CSS(层叠样式表)的模式,引⼊了QSS Qt本⾝的设计理念和⽹⻚前端还是存在⼀定差异的,因此QSS中只能⽀持部分CSS属性整体来说QSS要⽐CSS更简单⼀些 注意:如果通过QSS设置的样式和通过C++代码设置的样式冲突,则QSS优先级更⾼1.基本语法
语法: 对于CSS来说,基本的语法结构⾮常简单选择器{属性名 : 属性值;}
QSS沿⽤了这样的设定选择器{属性名 : 属性值;}
说明: 选择器:描述了"哪个Widget要应⽤样式规则" 指定控件之后,此时的样式会针对这个指定控件生效,也会对其子控件生效既要考虑到子控件,也要考虑到此时选择器是针对那个"类型"的控件 属性:是⼀个键值对,属性名表⽰要设置哪种样式,属性值表⽰了设置的样式的值 示例:QPushButton{color : red;}
2.QSS设置方式
1.指定控件样式设置
QWidget
中包含了setStyleSheet()
⽅法,可以直接设置样式示例:ui->pushButton->setStyleSheet("QPushButton { color: red; }");
2.全局样式设置
通过QApplication
的setStyleSheet()
⽅法设置整个程序的全局样式全局样式优点: 使同⼀个样式针对多个控件⽣效,代码更简洁所有控件样式内聚在⼀起,便于维护和问题排查 示例:int main(int argc, char *argv[]){ QApplication a(argc, argv); a.setStyleSheet("QPushButton { color: red; }");// ...}
如果设置了全局样式,然后在某个控件里又设置了其他的样式,会怎样? 两方面的样式会"叠加"起来 --> 样式的层叠特性 如果设置了全局样式,在某个控件里设置的样式和全局样式冲突了,会怎样? 局部样式的优先级更高,覆盖对应的全局样式 总结: 实际开发中,可以在全局样式中设置比较通用的样式,统一整个程序的界面风格如果需要针对某个个控件进行微调,可以使用局部样式来做出调整 3.从文件加载样式表
上述方法都是把样式通过硬编码的⽅式设置的 这样使QSS代码和C++代码耦合在⼀起了,并不⽅便代码的维护 更好的做法是把样式放到单独的⽂件中,通过读取⽂件的⽅式来加载样式示例:QString LoadQSS() { QFile file(":/style.qss"); file.open(QFile::ReadOnly); QString style = file.readAll(); file.close(); return style;}int main(int argc, char *argv[]){ QApplication a(argc, argv); // 设置全局样式 a.setStyleSheet(LoadQSS());// ...}
4.使⽤Qt Designer编辑样式
QSS也可以通过Qt Designer直接编辑,从⽽起到实时预览的效果,同时也能避免C++和QSS代码的耦合这种⽅式设置样式,样式内容会被以xml格式记录到ui⽂件中具体操作本篇文章不做展开,在软件内部很容易就能知道如何操作5.总结
当发现⼀个控件的样式不符合预期的时候,要记得排查这四个地⽅ 全局样式(QApplication 设置的)指定控件样式指定控件父控件的样式(可能是从父控件继承过来的)QSS文件中的样式ui文件中的样式 实际开发中,如果需要设置样式,建议最好统一使用某一种方式来进行设置3.选择器
1.选择器概况
QSS的选择器⽀持以下⼏种,其规则和CSS选择器基本一致 全局选择器:选择所有的widget
类型选择器(type selector):以QPushButton
为例 选择所有的QPushButton
和其⼦类的控件 类选择器(class selector):以.QPushButton
为例 选择所有的QPushButton
的控件,不会选择⼦类 ID选择器:以#pushButton_2
为例 选择objectName
为pushButton_2
的控件通过类型选择器和ID选择器设置了冲突的样式时,ID选择器样式优先级更⾼ 后代选择器:以QDialog QPushButton
为例 选择QDialog
的所有后代(⼦控件,孙⼦控件等)中的QPushButton
⼦选择器:以QDialog>QPushButton
为例 选择QDialog
的所有⼦控件中的QPushButton
并集选择器:以QPushButton, QLineEdit, QComboBox
为例 选择QPushButton, QLineEdit, QComboBox
这三种控件,接下来的样式会针对这三种控件都⽣效并集选择器是⼀种很好的代码复⽤的⽅式 很多时候希望界⾯上的多个元素⻛格是统⼀的,就可以使⽤并集选择器,把样式属性同时指定给多种控件 属性选择器:以QPushButton[flat="false"]
为例 选择所有QPushButton
中,flat
属性为false
的控件 优先级问题? 简单总结: 选择器描述的范围越精准,则优先级越⾼⼀般来说,ID选择器优先级是最⾼的 Qt⽂档上有具体的优先级规则介绍(参⻅The Style Sheet Syntax的Conflict Resolution章节) 示例:// QString style = "QPushButton { color: red; font-size: 50px; }";// style += "#pushButton_2 { color: green;} ";// style += "#pushButton_3 { color: blue;} ";// 并集选择器:如果想要设置的属性一样,可以用以下代码QString style = "#pushButton_2, QLineEdit, QLabel { color: red; }";a.setStyleSheet(style);
2.子控件选择器
有些控件内部包含了多个"⼦控件" 例如:QComboBox
的下拉后的⾯板、QSpinBox
的上下按钮等哪些控件拥有哪些⼦控件,参考⽂档Qt Style Sheets Reference中List of Sub-Controls章节 可以通过⼦控件选择器::
,针对上述子空间进行样式设置示例:QString style = "QComboBox::down-arrow { image: url(:/down.png); }";a.setStyleSheet(style);
3.伪类选择器
根据控件所处的某个状态被选择的,也可以理解为"伪状态选择器" 当状态具备时,控件被选中,样式⽣效当状态不具备时,控件不被选中,样式失效例如:按钮被按下、输⼊框获取到焦点、⿏标移动到某个控件上等 使⽤:
的⽅式定义伪类选择器常用的伪类选择器: :hover
:鼠标放到控件上:pressed
:⿏标左键按下时:focus
:获取输⼊焦点时:enabled
:元素处于可⽤状态时:checked
:被勾选时:read-only
:元素为只读状态时以上状态都可以用!
来取反 例如::!hover
就是⿏标离开控件时,:!pressed
就是⿏标松开时 更多伪类选择器的详细情况,参考Qt Style Sheets Reference的Pseudo-States章节此处同样的功能,事件也可以实现,但是用伪类选择器要比事件的方式简单很多示例:QString style = "QPushButton { color: red; } "; // 默认状态style += "QPushButton:hover { color: green; } "; // 特定状态style += "QPushButton:pressed { color: blue; }"; // 特定状态a.setStyleSheet(style);