QT跨平台应用程序开发框架(12)—— Qt界面样式优化

目录

一,关于 QSS

1.1 关于 CSS 

1.2 基本使用

1.3 两个问题

1.4 qss 文件

二,选择器

2.1 基本用法

2.2 子控件选择器

2.3 伪类选择器

三,盒模型

四,控件样式示例

4.1 按钮

4.2 复选框

4.3 输入框

4.4 列表框

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 要设定样式”
  • 属性:是一个或多个键值对,属性名表示要设置哪种属性,属性值表示设置的样式的值

 例如下面实例表示把所有按钮的文本颜色设置为 红色

QPushButton {
    color: red;
}

我们前面介绍 QWidget 常用属性时,已经介绍了 QSS 的两种设置方式:QT跨平台应用程序开发框架(4)—— 常用控件QWidget-CSDN博客

一种是直接代码设置,一种是在 ui 里设置

在代码设置就设置 setStyleSheet 属性即可:

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 的内容:

#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 章节

 下面演示一下,比如我要让一个按钮在:“未按下”、“鼠标移动上去”、“鼠标按下”三种状态时,立马的文字分别显示不同颜色,如下代码:

#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

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

 ②示例二:设置外边距

#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 设置样式:

QPushButton {
    font-size: 20px;
    border: 2px solid #8f8f91; /*边框颜色*/
    border-radius: 15px; /*圆角矩形*/
    background-color: #dadbde; /*按钮背景颜色*/
 }
 QPushButton:pressed {
    background-color: #f6f7fa; /*按钮按下时的背景颜色*/
 }

4.2 复选框

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

 然后创建一个 Check Box,右键改变样式表:

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 控件并输入样式:

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控件,双击控件可以添加元素,添加元素后添加下列样式:

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 的项目,添加部分菜单栏:

输入下列样式:

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 添加下列样式:

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;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值