目录
[一,关于 QSS](#一,关于 QSS)
[1.1 关于 CSS](#1.1 关于 CSS)
[1.2 基本使用](#1.2 基本使用)
[1.3 两个问题](#1.3 两个问题)
[1.4 qss 文件](#1.4 qss 文件)
[2.1 基本用法](#2.1 基本用法)
[2.2 子控件选择器](#2.2 子控件选择器)
[2.3 伪类选择器](#2.3 伪类选择器)
[4.1 按钮](#4.1 按钮)
[4.2 复选框](#4.2 复选框)
[4.3 输入框](#4.3 输入框)
[4.4 列表框](#4.4 列表框)
[4.5 菜单](#4.5 菜单)
前端开发 CSS 介绍:前端学习(2)------ CSS详解与使用_前端css-CSDN博客
一,关于 QSS
一个程序的界面是否好看也是非常重要的,所以界面优化也可以叫做界面"美化"
- 面向专业领域的程序,不关心界面如何,更在意实际效果
- 面向普通用户的程序,界面观感,是很大的加分项
1.1 关于 CSS
QSS 其实非常类似于网页前端开发的 CSS,可以参考:前端学习(2)------ CSS详解与使用_前端css-CSDN博客
它能够针对界面的"样式"来进行设置, 比如:大小,位置,颜色,背景等等
由于 QSS 是对 CSS 的模仿,所以在某些地方,QSS 比 CSS 要逊色一些,但是够用
1.2 基本使用
CSS 的语法结构非常简单,所以 QSS 沿用了这样的设定:
选择器 {
属性名: 属性值;
}
- 选择器:描述了"哪个 widget 要设定样式"
- 属性:是一个或多个键值对,属性名表示要设置哪种属性,属性值表示设置的样式的值
例如下面实例表示把所有按钮的文本颜色设置为 红色:
css
QPushButton {
color: red;
}
我们前面介绍 QWidget 常用属性时,已经介绍了 QSS 的两种设置方式:QT跨平台应用程序开发框架(4)------ 常用控件QWidget-CSDN博客
一种是直接代码设置,一种是在 ui 里设置
在代码设置就设置 setStyleSheet 属性即可:
css
ui->pushButton->setStyleSheet("QPushButton { color: red; }");
一种是直接在 ui 界面添加,可以找到控件的 styleSheet 属性:

或者直接右键控件:


1.3 两个问题
问题一:如果设置了全局样式,然后又在某个空间里设置了其它的样式会怎样?
我们先创建三个按钮, 然后在 main.cpp 里设置全局样式,运行后按钮就会变为红色:

这时候,我们再去控件里再去设置样式,比如我们设置字体大小,结果变成了这样:

问题解答:可以看到,两方面的样式会"叠加"起来
问题二:如果设置了全局样式,再在某个空间里设置和全局样式冲突的样式如何?
比如我们全局样式设置红色,那我们就单独设置个 绿色,如下:

问题解答:可以看到,当冲突的时候,局部样式的优先级大于全局样式,可以说是先渲染了全局样式,后渲染的局部样式,导致局部样式覆盖了全局样式
1.4 qss 文件
- 我们都知道,要把一个控件调成好看,肯定不止一条 QSS 语句,所以,如果我们像上面一样,C++ 的代码和 QSS 的代码混杂在一起,体量一大,代码维护成本直线飙升
- 所以我们可以和前端开发一样,把 QSS 代码单独拿出来,放进一个 qss文件里,后续直接让 C++ 来读取加载文件内容,就可以完成 "基本代码" 和 "样式代码" 的"解耦",下面来演示一下
我们仍然用到 qrc 机制,这里不再赘述
创建好后,我们手动在电脑的文件管理器的项目目录下,新建一个 style.qss 文件,就和图片文件一样,只是图片变成了 .qss 文件,其余操作完全一致
在 qss 文件里设置和上面一样的改变按钮字体的样式后,就可以使用 C++ 代码来加载 qss 文件了,下面是 main.cpp 的内容:
cpp
#include "widget.h"
#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();
}
到了先在我们一共知道了三种设置样式的方法:C++ 代码添加、qss文件、ui界面添加
- 但是最简单的还是直接在 ui 界面添加,只需要右键对应控件,点击"改变样式表"即可,它会直接添加进 ui 文件里,并且支持实时预览
- 但是也由于设置样式太灵活,就导致某个控件样式不和预期时,排查起来比较麻烦
二,选择器
2.1 基本用法
选择器的含义可以参考:前端学习(2)------ CSS详解与使用_前端css-CSDN博客
这里不再赘述,下面是QSS 的部分支持的选择器,其中加粗的是比较重要的常用选择器:
选择器名称 | 示例 | 说明 |
---|---|---|
全局选择器 | * | 选择所有的 widget |
类型选择器(type selector) | QPushButton | 选择所有的 QPushButton 和 其子类的控件 |
类选择器 | .QPushButton | 选择所有 QPushButton 的控件,不过不会选择子类 |
ID 选择器 | #pushButton_2 | 选择特定 objectName 的控件 |
后代选择器 | QDialog QPushButton | 选择 QDialog 的所有后代中的 QPushButton |
子选择器 | QDialog>QPushButton | 选择 QDialog 的所有子空间中的 QPushButton |
并集选择器 | QPushButton, QLineEdit, QComboBox | 选择指定的一种或多种控件,样式单独对这些控件生效,可和前面的嵌套使用 |
属性选择器 | QPushButton[flat="false"] | 选择所有 QPushButton 中,flat 属性为 false 的控件 |
①类型选择器

如果用 小点点 开头,那么就会变成类选择器,此时只会针对 QWidget 生效,不会对子类的 QPushButton 生效
②ID 选择器
单独针对一个控件进行的修改,如下:

注意:
- 当某个控件,通过类型和 ID 选择器设置了冲突的样式,ID 选择器优先级更高
- 同理,选择器也很多,也会涉及到优先级问题,Qt 文档上有具体的优先级规则介绍(可参考 The Style Sheet Syntax 的 Conflict Resolution 章节)
- 当然,如何属性不冲突,那么也会相互叠加
③并集选择器
我们先创建三个不同的样式,然后可以使用并集选择器设置样式:

2.2 子控件选择器
部分控件内部包含了多个"子空间",比如 QComboBox 的下拉框的多个内容和 QSpinBox 微调框的上下选择按钮等,我们可以通过 子控件选择器"两个冒号",针对子空间进行样式设置
可以参考 Qt 文档 QtStyleSheetsReference 中 ListofSub-Controls 章节
下面简单演示一下,将下拉框的下拉按钮替换成别的图片:

2.3 伪类选择器
前面介绍的选择器都是选中控件,而伪类选择器选中的是控件的"状态",或者是选择"符合一定状态条件的控件",常用的伪类选择器如下:
伪类选择器 | 说明 |
---|---|
:hover | 鼠标放到控件上 |
:pressed | 鼠标左键按下时 |
:focus | 获取输入焦点时 |
:enabled | 元素处于可用状态时 |
:checked | 被勾选时 |
:read-only | 元素为只读状态时 |
状态可以用 ! 来取反,比如 :!hover 激素鼠标离开控件时,:!pressed 就是鼠标松开时
更多内容可以参考 Qt 文档 QtStyleSheetsReference 的 Pseudo-States 章节
下面演示一下,比如我要让一个按钮在:"未按下"、"鼠标移动上去"、"鼠标按下"三种状态时,立马的文字分别显示不同颜色,如下代码:
cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style = "";
style += "QPushButton { color: red; }";
style += "QPushButton:hover { color: green; }";
style += "QPushButton:pressed { color: blue; }";
a.setStyleSheet(style);
Widget w;
w.show();
return a.exec();
}

上面的操作也可以通过事件来实现,但是比较麻烦,这里就不展示了,哪种方式便捷就选哪个
QSS 中样式非常多,不用特意去记忆,要用哪个就查哪个,而且大多数属性和 CSS 是一样的,文档的 Qt Style Sheet Reference 章节有详细介绍
三,盒模型
文档的 Customizing Qt Widgets Using Style Sheets 的 The Box Model 章节介绍了盒模型

关于盒模型我们的 CSS 文章里也有介绍,具体细节不再赘述:前端学习(2)------ CSS详解与使用_前端css-CSDN博客
可以通过一些 QSS 属性来设置上述的边距和边框的样式:
QSS 属性 | 说明 |
---|---|
margin | 设置四个方向的外边距,复合属性(left,right,top,bottom) |
padding | 设置四个方向的内边距,复合属性 |
border-style | 设置边框样式 |
border-width | 边框粗细 |
border-color | 边框颜色 |
border | 相当于 border-style + border-width + border-color |

①示例一:设置边框和内边距

②示例二:设置外边距
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton(this);
btn->setGeometry(0, 0, 100, 100);
btn->setText("hello");
btn->setStyleSheet("QPushButton { border: 5px solid red; margin: 20px; }");
const QRect& rect = btn->geometry();
qDebug() << rect;
}
Widget::~Widget()
{
delete ui;
}

虽然红色边框让按钮的白色区域看起来变小了,但是实际上控件的占用面积没有改变
四,控件样式示例
4.1 按钮
我们创建一个按钮,直接右键"改变样式表",使用 Qt Designer 设置样式:
css
QPushButton {
font-size: 20px;
border: 2px solid #8f8f91; /*边框颜色*/
border-radius: 15px; /*圆角矩形*/
background-color: #dadbde; /*按钮背景颜色*/
}
QPushButton:pressed {
background-color: #f6f7fa; /*按钮按下时的背景颜色*/
}

4.2 复选框
先在 阿里巴巴矢量图标库下载类似下面的图片:

然后创建一个 Check Box,右键改变样式表:
css
QCheckBox {
font-size: 20px;
}
QCheckBox::indicator {
width: 20px;
height: 20px;
}
QCheckBox::indicator:unchecked {
image: url(:/box/checkbox-unchecked.png);
}
QCheckBox::indicator:unchecked:hover {
image: url(:/box/checkbox-unchecked_hover.png);
}
QCheckBox::indicator:unchecked:pressed {
image: url(:/box/checkbox-unchecked_pressed.png);
}
QCheckBox::indicator:checked {
image: url(:/box/checkbox-checked.png);
}
QCheckBox::indicator:checked:hover {
image: url(:/box/checkbox-checked_hover.png);
}
QCheckBox::indicator:checked:pressed {
image: url(:/box/checkbox-checked_pressed.png);
}

属性 | 说明 |
---|---|
::indicator | 子控件选择器 选中 checkbox 中的对钩部分 |
:hover | 伪类选择器 鼠标移动上去的状态 |
:pressed | 伪类选择器 鼠标按下的状态 |
:checked | 伪类选择器 checkbox 被选中的状态 |
:unchecked | 伪类选择器 checkbox 未被选中的状态 |
width | 设置子控件宽度 对于普通控件无效(普通控件使用 geometry 方式设定尺寸) |
height | 设置子控件高度 对于普通控件无效(普通控件使用 geometry 方式设定尺寸) |
image | 设置子控件的图片 像 QSpinBox,QComboBox 等可以使用这个属性来设置子控件的图片 |
4.3 输入框
创建一个Line Edit 控件并输入样式:
css
QLineEdit {
border-width: 1px;
border-radius: 10px;
border-color: rgb(58, 58, 58);
border-style: inset;
padding: 0 8px;
color: rgb(255, 255, 255);
background:rgb(100, 100, 100);
selection-background-color: rgb(187, 187, 187);
selection-color: rgb(60, 63, 65);
}

属性 | 说明 |
---|---|
border-width | 设置边框宽度 |
border-radius | 设置圆角矩形 |
border-color | 设置边框颜色 |
border-style | 设置边框风格 |
padding | 设置内边距 |
color | 设置文字颜色 |
background | 设置背景颜色 |
selection-background-color | 设置选中文字的背景颜色 |
selection-color | 设置选中文字的文本颜色 |
4.4 列表框
在界面上创建一个 List Widget控件,双击控件可以添加元素,添加元素后添加下列样式:
cpp
QListView::item:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #FAFBFE, stop: 1 #DCDEF1);
}
QListView::item:selected {
border: 1px solid #6a6ea9;
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #6a6ea9, stop: 1 #888dd9);
}

属性 | 说明 |
---|---|
::item | 选中控件的子控件 |
:hover | 选中鼠标悬停的条目 |
:selected | 选中某个被选中的条目 |
background | 设置背景颜色 |
border | 设置边框 |
qlineargradient | 设置渐变色 |
关于:qlineargradient
这是设置渐变色的一个属性,有 6 个参数,比如上面的样例,x1 和 y1 表示起点,x2 和 y2 表示终点,就像平面直角坐标系的两个点一样,这两个点描述了一个方向:
- x1:0, y1:0, x2:0, y2:1,就是垂直方向从上向下进行颜色渐变
- x1:0, y1:0, x2:1, y2:0,就是水平方向从左向右进行颜色渐变
- x1:0, y1:0, x2:1, y2:1,就是从左上往右下方向进行颜色渐变
而上面例子后面的 stop 的两个参数,表示颜色从 stop0 向 stop1 进行渐变
4.5 菜单
先创建一个继承 QMainWindow 的项目,添加部分菜单栏:

输入下列样式:
css
QMenuBar {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 lightgray, stop:1 darkgray);
spacing: 3px; /*多个菜单之间的空隙*/
}
QMenuBar::item {
padding: 1px 4px;
background: transparent;
border-radius: 10px;
}
QMenuBar::item:selected {
background: #a8a8a8;
}
QMenuBar::item:pressed {
background: #888888;
}
QMenu {
background-color: white;
margin: 0 2px; /*外边距*/
}
QMenu::item {
padding: 2px 25px 2px 20px;
border: 3px solid transparent;
}
QMenu::item:selected {
border-color: darkblue;
background: rgba(100, 100, 100, 150);
}
QMenu::separator {
height: 2px;
background: lightblue;
margin-left: 10px;
margin-right: 5px;
}

属性 | 说明 |
---|---|
QMenuBar::item | 选中菜单栏的元素 |
QMenuBar::item:selected | 选中菜单栏中被选中的元素 |
QMenuBar::item:pressed | 选中菜单栏中鼠标点击的元素 |
QMenu::item | 选中菜单中的元素(注意菜单和菜单栏的区别) |
QMenu::item:selected | 选中菜单中被选中的元素 |
QMenu::separator | 选中菜单中的分割线 |
五,实现登录页面
先创建下列控件:
准备一张图片,使用 prc 机制设置背景,符合直觉的做法,就是直接给 QWidget 顶层窗口设置背景图,但是 Qt 中有某种不明限制,直接给顶层窗口设置背景会失效
那么我们可以在上面控件上再套一个和窗口一样大小的 QFrame 控件(是 QWidget 的一个子类),再给这个 QFrame 用图片填充即可:

给 QWidget 或者 QFrame 添加下列样式:
cpp
QFrame {
border-image: url(:/background.png);
/*相较于 background-image,这个的背景会自动跟随控件大小变化,前者是固定大小*/
}
/*输入框样式*/
QLineEdit {
color: #8d98a1; /*文本颜色*/
background-color: #405361;
padding: 0 5px;
font-size: 20px;
border-style: none;
border-radius: 10px;
}
/*设置 checkbox样式*/
QCheckBox {
color: white;
background-color: transparent;
}
/*设置按钮样式*/
QPushButton {
font-size: 20px;
color: white;
background-color: #555;
border-style: outset;
border-radius: 10px;
}
QPushButton:pressed {
color: black;
background-color: #ced1db;
border-style: inset;
}

里面各控件的功能我们前面都实现过,这里不再赘述