【Qt】界面优化(1)------QSS
- 1.QSS
- 2.选择器
- 3.子控件选择器
- [4. 伪类选择器(Pseudo-States)](#4. 伪类选择器(Pseudo-States))
- [5. 盒子模式](#5. 盒子模式)
- 6.常用控件样式
1.QSS
1.1QSS简介
Qt仿照了CSS的模式,引入了QSS,来对Qt中的空间进行样式设计。当然由于Qt本身的设计理念和网页前端还是有一定差别的,因此QSS中只能支持部分呢的CSS样式,总体来说QSS要比CSS更简单一些。
注意:如果通过QSS设置样式和C++代码设置样式产生了冲突,QSS样式的优先级更高
基本语法:
选择器 {
属性名: 属性值;
}
- 选择器:描述要对那个控件进行样式设计
- 属性:使用一个键值对表示,属性名表示要设置哪种样式,属性名表示设置样式的值
例如:
c
QPushButton { color: red; }
1.2QSS设置方式
- 指定控件样式设置
QWidget 中包含了setStyleSheet 方法,可以直接设置样式.另一方面,给指定控件设置样式之后,该控件的子元素也会受到影响.
c
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton->setStyleSheet("QPushButton{color: red;}");
}
子元素收到影响,这次修改widget.cpp,我们不再给按钮设置样式,而是给Widget设置样式(Widget是QPushButton的父控件).同样能得到上述的效果
c
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setStyleSheet("QPushButton{color: red;}");
}
- 全局样式设置
还可以通过QApplication 的setStyleSheet 方法设置整个程序的全局样式.
全局样式优点:
- 使同⼀个样式针对多个控件生效,代码更简洁.
- 所有控件样式内聚在⼀起,便于维护和问题排查.
例如我们在出口商放置多个按钮,并直接通过全局设置给他们设置样式
c
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置全局样式
a.setStyleSheet("QPushButton { color: red; }");
Widget w;
w.show();
return a.exec();
}
但是有时候我们除了使用全局样式设置外,还可能在具体的控件上在此设置一次样式,所以这里Qt支持样式的层叠性,即如果通过全局样式给某个控件设置了属性1,通过指定控件样式给控件设置属性2,那么这两个属性都会产生作用,这个作用是叠加起来的。
例如还是使用上述的的设置全局样式的代码,并且在widget.cpp中对一个具体的按钮设置字体大小
c
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置指定控件样式
ui->pushButton->setStyleSheet("QPushButton { font-size: 50px} ");
}
运行程序,可以看到,对于第⼀个按钮来说,同时具备了颜色和字体大小样式.而第⼆个和第三个按钮只有颜样式.说明针对第⼀个按钮,两种设置方式设置的样式,叠加起来了.

还有一种情况就是,当全局和针对性的对某个控件(局部)的修改样式的操作一样的时候,这里遵循局部优先的原则。就比如我们全局对按钮的字体设置为红色,但是后期再代码中对按钮又设置为绿色,那么按钮最终就会变成绿色。
这里我们仅仅只修改一下widget.cpp中的代码
c
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton->setStyleSheet("QPushButton{color: blue;}");
}

- 从文件加载样式
上述代码都是把样式通过硬编码的方式设置的.这样使QSS代码和C++代码耦合在⼀起了,并不方便代码的维护.因此更好的做法是把样式放到单独的文件中,然后通过读取文件的方式来加载样式.
首先创建style.qss 文件,并添加到resource.qrc 中,由于Qt中没有提供创建qss文件的选项,所以我们需要手动创建qss文件

c
#include <QApplication>
#include <QFile>
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());
Widget w;
w.show();
return a.exec();
}
- 使用Qt Designer编辑样式
QSS也可以通过Qt Designer直接进行编辑,从而起到实时预览的效果。同时也能避免 C++和QSS代码的耦合.而实现起来也是简单,只需要找到想要修改样式的控件->然后鼠标右击->选择改变样式表即可在里面编辑样式。

而这种设置样式的方式,样式内容会被一xml格式的方式记录到ui文集中。
c
<property name="styleSheet">
<string notr="true">QPushButton { color: red; }</string>
</property>
1.3样式文档

2.选择器
| 选择器 | 示例 | 说明 |
|---|---|---|
| 全局选择器 | * | 选择所有的widget |
| 类型选择器(type selector) | QPushButton | 选择所有的QPushButton和其子控件 |
| 类选择器(class selector) | .QPushButton | 选择所有的QPushButton,不会选择其子控件 |
| ID选择器 | #pushButton_1 | 选择objectName 为pushButton_1 的控件. |
| 后代选择器 | QDialog QPushButton | 选择QDialog的所有后代(子控件,孙子控件等等)中的QPushButton. |
| 子选择器 | QDialog>QPushButton | 选择QDialog的所有子控件中的QPushButton. |
| 并集选择器 | QPushButton,QLineEdit,QComboBox | 选择QPushButton,QLineEdit,QComboBox这三种控件,(即接下来的样式会针对这三种控件都生效) |
| 属性选择器 | QPushButtonflat="false" | 选择所有QPushButton中,flat属性为false的控件 |
总体来说,QSS选择器的规则和CSS选择器基本⼀致.
注意:实践中我们可以简单的认为,选择器描述的范围越精准,则优先级越高,⼀般来说,ID选择器优先级是最高的.
3.子控件选择器
有些控件包含多个子控件,比如QCombBox的下拉面板,又比如QSpinBox的上下按钮和QProgressBar等。可以通过子控件选择器::,针对上述的子控件进行样式设置。

其中所有的子控件也可以在文档中查看

4. 伪类选择器(Pseudo-States)
前面我们都是根据具体的控件来进行选择修改样式的,但是伪类选择器则是根据状态来进行选择的,比如按钮,鼠标放到按钮上的时候被选择,或者当鼠标按下按钮的时候被选择,又或者是鼠标离开按钮时被选择。使⽤:的方式定义伪类选择器.
常用的伪类选择器
| 伪类选择器 | 说明 |
|---|---|
| :hover | 鼠标放在控件上 |
| :pressed | 鼠标左键按下 |
| :focus | 获取输入焦点时 |
| :enabled | 元素处于可用状态时 |
| :checked | 被勾选时 |
| :read-only | 元素为只读状态时 |
当然具体的可以查阅文档

这些状态可以使用! 来取反.比如:!hover 就是鼠标离开控件时,:!pressed 就是鼠标松开时,等等.
5. 盒子模式
在文档的Customizing Qt Widgets Using Style Sheets 的The Box Model 章节介绍了盒模型。

一个遵守盒模型的控件,由上述几个部分构成:
- Content矩形区域:存放控件内容.比如包含的文本/图标等
- Border矩形区域:控件的边框.
- Padding矩形区域:内边距.边框和内容之间的距离.
- Margin矩形区域:外边距.边框到控件geometry返回的矩形边界的距离
默认情况下,外边距,内边距,边框宽度都是0.
可以通过一些QSS属性来设置上述的边距和边框的样式.
| QSS属性 | 说明 |
|---|---|
| margin | 设置四个方向的外边距.复合属性. |
| padding | 设置四个方向的内边距.复合属性 |
| border-style | 设置边框样式 |
| border-width | 边框的粗细 |
| border-color | 边框的颜色 |
| border | 复合属性,相当于border--style+border-width+border-color,设置的时候顺序无所谓 |
c
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* button = new QPushButton(this);
button->setGeometry(0, 0, 100, 100);
button->setText("按钮");
// 设置边框5像素,加粗,红色,外边距10像素
button->setStyleSheet("QPushButton{border: 5px solid red; margin: 10px;}");
qDebug() << button->geometry();
}

从结果上看,我们修噶样式之后,按钮的QRect属性其实没有改变,还是之前我么设置的。
6.常用控件样式
- 自定义按钮
| 属性 | 说明 |
|---|---|
| font-size | 设置文字大小. |
| border-radius | 设置圆角矩形数值设置的越大,角就"越圆" |
| background-color | 设置背景颜色. |
- 复选框
| 属性 | 说明 |
|---|---|
| ::indicator | 子控件选择器,选中checkbox中的对钩部分. |
| :hover | 伪类选择器。选中鼠标移动上去的状态。 |
| :pressed | 伪类选择器。选中鼠标按下的状态, |
| :checked | 伪类选择器,选中checkbox被选中的状态. |
| :unchecked | 伪类选择器.选中checkbox未被选中的状态. |
| width | 设置子控件宽度,对于普通控件无效(普通控件使用geometry方式设定尺寸). |
| height | 设置子控件高度,对于普通控件无效(普通控件使用geometry方式设定尺寸), |
| image | 设置子控件的图片像QSpinBox,.QComboBox等可以使用这个属性来设置子控件的图片. |
- 单选框
| 属性 | 说明 |
|---|---|
| ::indicator | 子控件选择器。选中radioButton中的对钩部分 |
| :hover | 伪类选择器选中鼠标移动上去的状态。 |
| :pressed | 伪类选择器。选中鼠标按下的状态 |
| :checked | 伪类选择器,选中radioButton被选中的状态, |
| unchecked | 伪类选择器。选中radioButton未被选中的状态. |
| width | 设置子控件宽度,对于普通控件无效(普通控件使用geometry方式设定尺寸), |
| height | 设置子控件高度,对于普通控件无效(普通控件使用geometry方式设定尺寸), |
| image | 设置子控件的图片,像QSpinBox,QComboBox等可以使用这个属性来设置子控件的图片。 |
- 输入框
| 属性 | 说明 |
|---|---|
| border-width | 设置边框宽度. |
| border-radius | 设置边框圆角. |
| border-color | 设置边框颜色. |
| border-style | 设置边框风格。 |
| padding | 设置内边距, |
| color | 设置文字颜色, |
| background | 设置背景颜色. |
| selection-background-color | 设置选中文字的背景颜色. |
| selection-color | 设置选中文字的文本颜⾊. |
- 列表
| 要点 | 说明 |
|---|---|
| ::item | 选中QListView中的具体条目, |
| :hover | 选中鼠标悬停的条目 |
| :selected | 选中某个被选中的条目. |
| background | 设置背景颜色 |
| border | 设置边框。 |
| qlineargradient | 设置渐变色. |
关于qlineargradient,qlineargradient有6个参数.
- x1,y1:标注了一个起点.
- x2,y2:标注了一个终点.
- stop0和stop1描述了两个颜色.渐变过程就是从stop0往stopl进行渐变的.
这两个点描述了一个"方向"例如:
- x1:0,y1:0,x2:0,y2:1就是垂直方向从上向下进行颜色渐变,
- x1:0,y1:0,x2:1,y2:0就是水平方向从左向右进行颜色渐变.
- x1:0,y1:0,x2:1,y2:1就是从左上往右下方向进行颜色渐变.
c
QWidget {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop: 0 #fff, stop: 1 #000);
}
- 菜单栏
| 要点 | 说明 |
|---|---|
| QMenuBar::item | 选中菜单栏中的元素。 |
| QMenuBar::item:selected | 选中菜单来中的被选中的元素 |
| QMenuBar::item:pressed | 选中菜单栏中的鼠标点击的元素. |
| QMenu::item | 选中菜单中的元素 |
| QMenu::item:selected | 选中菜单中的被选中的元素. |
| QMenu::separator | 选中菜单中的分割线. |