当前位置: 首页 > news >正文

Qt——界面美化 QSS

文章目录

  • 界面美化 QSS
  • 全局样式
  • 样式和代码分离
  • 选择器
      • 类型选择器
    • 类选择器
    • ID选择器
    • 并集选择器
    • 子控件选择器
    • 伪类选择器
    • 渐变色
      • 线性渐变
      • 径向渐变
  • 盒子模型 Box Model
  • 样例
    • 修改复选框样式
    • 修改单行编辑框样式
    • 实现一个简单的登陆界面
        • QFrame 基本功能
  • 绘图
    • 绘制形状
    • 线段
      • 矩形
      • 文字
      • 图片

界面美化 QSS

类似于网页前端的CSS,可以对界面的各种样式进行设置

需要注意,如果QSS和C++代码同时对同一个控件的同一个属性进行了设置,那么QSS的优先级更高

QSS 基本格式:

选择器 {属性名:属性值;
}

例如,将窗口内所有的QPushBUtton的文本设置成红色:

#include "widget.h"#include "./ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->pushButton->setStyleSheet("QPushButton {color : rgb(200, 0, 100);}");
}Widget::~Widget() { delete ui; }

在这里插入图片描述

设置样式的时候,是可以指定某个控件来设置的。指定控件之后,此时的样式就会针对这个指定的控件和这个控件的子控件同时生效

例如:

#include "widget.h"#include "./ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setStyleSheet("QPushButton {color : rgb(200, 0, 100);}");
}Widget::~Widget() { delete ui; }

在这里插入图片描述


全局样式

通过main函数内部构造的QApplication类,进行全局样式设置

  • 如果设置了全局样式,然后在某个控件里面又设置了新的样式(不冲突),那么这个控件的样式就会叠加。即层叠性
  • 如果设置了全局样式,然后在某个控件里面又设置了同样的的样式,那么局部样式就会覆盖全局样式。即局部样式优先级高于全局样式
  • 所以,实际开发中,就可以设置通用的全局样式,来统一风格。如果需要对界面的某个控件进行微调,就可以使用局部样式

例如:

#include <QApplication>#include "widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;a.setStyleSheet("QPushButton {color : green;}");w.show();return a.exec();
}// widget.cpp
#include "widget.h"#include "./ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->pushButton_1->setStyleSheet("background-color : white;");		// 叠加性ui->pushButton_2->setStyleSheet("color : rgb(200, 0, 100);}");		// 局部样式优先级高于全局样式
}Widget::~Widget() { delete ui; }

在这里插入图片描述


样式和代码分离

如果涉及到的样式比较多,那么将其和C++代码混合明显是不合适的。

我们可以把样式代码拎出来,放到单独的文件中,后续可以直接让C++代码来读取并加载文件内容

Qt Designer中直接集成了上述功能,允许我们把样式直接写到 **.ui**文件里,并支持实时预览

在这里插入图片描述


选择器

选择器示例说明
全局选择器*选择所有的 widget.
类型选择器 (type selector)QPushButton选择所有的 QPushButton 和 其子类 的控件.
类选择器 (class selector).QPushButton选择所有的 QPushButton 的控件. 不会选择子类.
ID 选择器#pushButton_2选择 objectNamepushButton_2 的控件.
后代选择器QDialog QPushButton选择 QDialog 的所有后代(子控件, 孙子控件等等) 中的 QPushButton.
子选择器QDialog > QPushButton选择 QDialog 的所有子控件中的 QPushButton.
并集选择器QPushButton, QLineEdit, QComboBox选择 QPushButton, QLineEdit, QComboBox 这三种控件.
(即接下来的样式会针对这三种控件都生效).

类型选择器

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style = "QWidget {color : rgb(200, 50, 100);}";ui->layoutWidget->setStyleSheet(style);
}

通过类型选择器,将layoutWidget下的,所有QWidget及其子类的控件的文本设置颜色

效果:

在这里插入图片描述


类选择器

类选择器和类型选择器的区别是,类选择器不会选择指定控件类型的子类

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style = ".QWidget {color : rgb(200, 50, 100);}";ui->layoutWidget->setStyleSheet(style);
}

通过类选择器,将layoutWidget下的QWidget类型的控件的文本设置颜色

效果:

在这里插入图片描述


ID选择器

ID选择器只针**对传入的****objectName**的空间生效

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style = "#pushButton_1 {color : rgb(200, 50, 100);}";ui->layoutWidget->setStyleSheet(style);
}

使用ID选择器,对objectNamepushButton_1的控件,设置字体颜色

效果:

在这里插入图片描述


并集选择器

通过传入多个类型,样式会对传入的所有类型生效

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style = "QPushButton, QLineEdit {color : rgb(200, 50, 100);}";ui->layoutWidget->setStyleSheet(style);
}

通过并集选择器,将layoutWidget下的QPushButtonQLineEdit类型的控件设置字体颜色

效果:

在这里插入图片描述


子控件选择器

有些控件内部包含了多个“子控件“。比如QComboBox的下拉后的面板

可以通过子控件选择器::,针对上述子控件进行样式设置

哪些样式有哪些子控件,可通过下面的方式搜索:

Qt Assistant -> Qt Style Sheet Reference -> List of Sub-Controls

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style = "#comboBox::down-arrow{image : url(:/down)}";ui->comboBox->setStyleSheet(style);
}

利用ID选择器和子控件选择器,对objectNamecomboBox的下拉按钮设置图标

效果:

在这里插入图片描述


伪类选择器

并非选择一个控件,而是选择一个控件的状态

  • 当状态具备时,控件被选中,样式生效
  • 当状态不具备时,空间不被选中,样式不生效
伪类选择器说明
:hover鼠标放到控件上
:pressed鼠标左键按下时
:focus获取输入焦点时
:enabled元素处于可用状态时
:checked被勾选时
:read-only元素为只读状态时

注:可以通过 ! ,的方式,对状态取反

可以通过:Qt Assistant -> Qt Style Sheet Reference -> List of Pseudo-States。进行更详细的查看

例如:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QString style ="#pushButton:hover {background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 ""rgb(255, 100, 100), ""stop: 1 ""rgb(100, 255, 100));}";ui->pushButton->setStyleSheet(style);
}

利用伪类选择器,当**光标进入****pushButton**时,其背景颜色就会发生改变

效果:

在这里插入图片描述


渐变色

上面我们给pushButton设置背景颜色时,用到了渐变色。下面来介绍渐变色的设置方法

线性渐变

所谓线性渐变,就是沿着从左往右、从上往下、对角线的方向进行颜色渐变

可以对左上、右上、左下、右下分别标点为 (0, 0), (0, 1), (1, 0), (1, 1)

在这里插入图片描述

用到的方法为:qlineargradient

例如:

QPushButton {background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 red, stop: 1 yellow);
}
  • x1y1,即渐变起点的位置
  • x2y2,即渐变终点的位置
  • stop:渐变 stops 点,stop:0 对应起始颜色,stop:1 对应结束颜色,也可插入多个 stops 实现多色渐变,比如 stop:0 red, stop:0.5 green, stop:1 blue

径向渐变

即从中心向外围扩散的渐变方式

用到的方法为:qradialgradient

例如:

QPushButton {/* 圆心在控件中心(0.5, 0.5),半径 0.5(控件尺寸一半),颜色从中心白色渐变到边缘黑色 */background: qradialgradient(cx: 0.5, cy: 0.5, radius: 0.5, stop: 0 white, stop: 1 black);
}
  • cx, cy:渐变圆心坐标(0~1 范围,相对控件自身),(0.5, 0.5) 即控件中心。
  • radius:渐变半径(0~1 范围,相对于控件尺寸),0.5 表示以控件一半大小为半径。
  • stop:同线性渐变,控制颜色分布。

例如:

#dial::chunk {background : qradialgradient(cx: 0.5, cy: 0.5, radius: 0.5, stop: 0 green, stop: 1 blue);
}

在这里插入图片描述


盒子模型 Box Model

在这里插入图片描述

Qt中,每个Widget都是一个矩形,那么这个矩形,从里到外都可以分为四个部分:

  • CONTENT:内容

  • PADDING:内边距。内容区与边框(BORDER)之间的空白区域,用于控制内容与边框的间距,会影响元素整体占位大小(padding 会让元素 “变大” ),且背景色会覆盖内边距区域

  • BORDER:边距。包裹内容和内边距的线条,可设置样式border-style(如实线、虚线)、宽度border-width、颜色border-color,是元素视觉边界

  • MARGIN:外边距。最外层,用于控制当前元素与其他元素之间的空白间距,不影响元素自身大小,但会影响与相邻元素的布局关系(如上下元素的间距由 margin-top/margin-bottom 决定 ),且 外边距区域无背景色。 其可拆分为四个属性

    • margin-left
    • margin-right
    • margin-top
    • margin-bottom
    • 使用时,可以写为margin : 10px,即上下左右分别10px
    • 也可以写为margin: 10px, 20px,即上下10px,左右20px
    • 也可以写为margin: 10px, 20px, 30px, 40px,以上右下左的顺序(顺时针)进行设置
    • padding属性同理
  • 默认情况下marginpaddingborder-width为0
    例如:

Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QPushButton* button = new QPushButton(this);button->setText("这是一个按钮");button->setGeometry(0, 0, 300, 300);button->setObjectName("button");QString style ="#button {""border : 20px solid rgb(200, 100, 100);""padding : 50px;""margin : 30px;""text-align: left;"  // 改为左对齐"}";button->setStyleSheet(style);
}

效果:

在这里插入图片描述


样例

修改复选框样式

#checkBox {font-size : 20px;color : blue;
}#checkBox::indicator:unchecked {image : url(:/source/white-no.png);
}#checkBox:indicator:unchecked:hover {image : url(:/source/blue-no.png);
}#checkBox:indicator:unchecked:pressed {image : url(:/source/red-yes.png);
}#checkBox:indicator:checked {image : url(:/source/white-yes.png);
}#checkBox:indicator:checked:hover {image : url(:/source/blue-yes.png);
}#checkBox:indicator:checked:pressed {image : url(:/source/red-yes.png);
}

效果:

在这里插入图片描述


修改单行编辑框样式

#lineEdit {border-radius: 10px;border : 3px solid rgb(110, 110, 110);padding : 5px;font-size: 15px;background-color: rgb(197, 197, 197);color : rgba(1, 40, 49, 0.523);selection-background-color: rgb(116, 1, 1);		// 修改被选中文本的背景色selection-color: rgb(148, 243, 152);			// 修改被选中文本的文本色
}

效果:

在这里插入图片描述


实现一个简单的登陆界面

实现一个简单的登录页,包含以下功能:

  • 设置背景图片
  • 设置各个控件的样式
  • 可以控制用户密码的显示与隐藏
  • 可以根据窗口大小的变化,自动调节控件布局

注意:Qt不允许直接给主窗口QWidget设置背景图片,只能通过向主窗口添加一个QFrame控件,对这个frame进行背景图设置

QFrame 基本功能
  • 提供边框样式QFrame 可以设置多种边框样式,如 Box(矩形框)、Panel(面板样式)、Sunken(凹陷样式)、Raised(凸起样式) 等。通过设置边框样式,能让界面元素更具层次感和视觉吸引力。例如,在设计登录界面时,可以使用 QFrame 作为输入框区域的容器,并设置为凹陷样式,使其看起来像是一个独立的输入面板。
  • 背景和填充:除了边框,QFrame 还可以设置背景颜色或背景图片,从而进一步定制其外观。这对于创建具有特定风格的界面组件非常有用,比如为一个包含多个按钮的区域添加一个带有颜色或图案的背景。

Qt Desginer展示:

在这里插入图片描述

代码:

// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QResizeEvent>
#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void resizeEvent(QResizeEvent *event);private slots:void on_toolButton_clicked();private:Ui::Widget *ui;
};
#endif  // WIDGET_H// widget.cpp
#include "widget.h"#include <QLineEdit>
#include <QPushButton>#include "./ui_widget.h"Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->label->setAlignment(Qt::AlignCenter);// 设置背景图QString style_frame ="#frame {""border-image : url(:/background);""}";ui->frame->setStyleSheet(style_frame);// 设置输入框样式QString style_edit =".QLineEdit {""background-color : rgba(50, 50, 50, 0.7);""border : 1px solid rgb(160, 100, 200);""border-radius : 10px;""font-size : 15px;""padding : 5px;""}";ui->lineEdit->setStyleSheet(style_edit);ui->lineEdit_2->setStyleSheet(style_edit);ui->lineEdit->setEchoMode(QLineEdit::Normal);ui->lineEdit_2->setEchoMode(QLineEdit::Password);ui->lineEdit->setClearButtonEnabled(true);ui->lineEdit_2->setClearButtonEnabled(true);ui->lineEdit->setPlaceholderText("请输入用户uid");ui->lineEdit_2->setPlaceholderText("请输入密码");// 设置 ToolButton样式QString style_tool ="QToolButton {""    background-color: white !important;""    padding: 5px;""}";ui->toolButton->setStyleSheet(style_tool);ui->toolButton->setCheckable(true);ui->toolButton->setChecked(false);ui->toolButton->setIcon(QIcon(":/closeEyes"));// 设置pushButton样式QString style_push ="#pushButton {""   background: rgba(0, 0, 0, 0.6); ""   border-radius: 10px; ""   border: 1px solid rgba(255, 255, 255, 0.5); ""   color: white; ""   padding: 8px 20px; ""}""#pushButton:hover {""    background: rgba(255, 255, 255, 0.3); ""}""#pushButton:pressed {""   padding: 7px 3px 3px 7px;""   border: 1px solid darkgray;""}";ui->pushButton->setStyleSheet(style_push);
}Widget::~Widget() { delete ui; }void Widget::resizeEvent(QResizeEvent* event) {ui->frame->setGeometry(0, 0, event->size().width(), event->size().height());
}// 控制密码显示
void Widget::on_toolButton_clicked() {if (ui->toolButton->isCheckable() == false) {ui->toolButton->setIcon(QIcon(":/openEyes"));ui->toolButton->setCheckable(true);ui->lineEdit_2->setEchoMode(QLineEdit::Normal);} else {ui->toolButton->setIcon(QIcon(":/closeEyes"));ui->toolButton->setCheckable(false);ui->lineEdit_2->setEchoMode(QLineEdit::Password);}
}

绘图

有时候Qt已有的控件无法满足我们的需求,为了应对这种情况,就需要用到绘图,自己实现满足要求的控件

核心类:

说明
QPainter“绘画者” 或者 “画家”。
用来绘图的对象,提供了一系列 drawXXX 方法,可以允许我们绘制各种图形。
QPaintDevice“画板”。
描述了 QPainter 把图形画到哪个对象上。像咱们之前用过的 QWidget 也是一种 QPaintDevice(QWidget 是 QPaintDevice 的子类)。
QPen“画笔”。
描述了 QPainter 画出来的线是什么样的。
QBrush“画刷”。
描述了 QPainter 填充一个区域是什么样的。

画图的相关操作,一般不放到狗杂函数中进行。

Qt提供了一个**paintEvent**事件处理函数,在这里进行绘图调用。当QpaintEvent事件触发的时候,事件函数就会执行

  • 控件首次创建的时候
  • 空间被遮挡,然后被解除遮挡的时候
  • 窗口被最小化,然后被还原的时候
  • 控件大小发生改变的时候
  • 主动在代码中调用repaint或者update的时候

绘制形状

线段

void QPainter::drawLine(int x1, int y1, int x2, int y2)
void QPainter::drawLine(const QPoint &p1, const QPoint &p2)

指定起点和终点的横纵坐标,绘制线段

矩形

void QPainter::drawRect(int x, int y, int width, int height)

指定左上角坐标,指定长宽

void QPainter::drawEllipse(int x, int y, int width, int height)

指定圆心横纵坐标,并确定外接矩形的高和宽

文字

void QPainter::drawText(int x, int y, const QString &text)
void QPainter::drawText(const QPoint &position, const QString &text)
  • x:是文字的最左侧位置
  • y:是文字的基线位置。四线格的第三根线

在这里插入图片描述

例如:

#include "widget.h"#include <QBrush>
#include <QPainter>
#include <QPen>#include "./ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); }Widget::~Widget() { delete ui; }void Widget::paintEvent(QPaintEvent *evnet) {QPainter painter(this);QPen pen;pen.setColor("red");                   // 设置画笔颜色pen.setWidth(2);                       // 设置画笔宽度pen.setStyle(Qt::PenStyle::DashLine);  // 设置画笔类型painter.setPen(pen);  // 讲画笔设置给画家painter.drawLine(10, 10, 88, 88);  // 画线段painter.setFont(QFont("微软雅黑", 20));   // 设置画家字体painter.drawText(300, 50, "HELLO WORD");  // 写字// 设置径向渐变画刷QLinearGradient gradient(100, 100, 500, 500);gradient.setColorAt(0, Qt::red);gradient.setColorAt(1, Qt::blue);QBrush brush(gradient);  // 直接用渐变初始化画刷(无需额外设置样式)painter.setBrush(brush);  // 讲画刷设置给画家painter.drawEllipse(100, 100, 300, 300);  // 以 (100, 100)半径500px画圆// 设置brush.setColor("white");brush.setStyle(Qt::HorPattern);painter.setBrush(brush);  // 讲画刷设置给画家// 画矩形painter.drawRect(400, 350, 200, 200);
}

效果:

在这里插入图片描述


图片

Qt 提供了四个类来处理图像数据:QImage、QPixmap、QBitmap 和 QPicture,它们都是常用的绘图设备。

  • QImage 主要用来进行 I/O 处理,它对 I/O 处理操作进行了优化,而且可以用来直接访问和操作像素

  • QPixmap 主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;

  • QBitmap 是 QPixmap 的子类,用来处理颜色深度为 1 的图像,即只能显示黑白两种颜色

  • QPicture 用来记录并重演 QPainter 命令

这里主要介绍QPixmap

void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
void QPainter::drawPixmap(int x, int y, int width, int height, const QPixmap &pixmap)
  • xy开始,绘制图片
  • 并将图片绘制成大小width * height

例如:

#include "widget.h"#include <QBrush>
#include <QPixmap>#include "./ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); }Widget::~Widget() { delete ui; }void Widget::paintEvent(QPaintEvent *evnet) {QPainter painter(this);QPixmap map(":/photo");painter.drawPixmap(20, 20, 800, 600, map);
}

效果:

在这里插入图片描述

如果想要旋转图像,以旋转180度为例,操作步骤如下:

  1. 保存当前坐标系状态

    painter.save();
    
  2. 旋转坐标轴(旋转画家)

    painter.rotate(180);
    
  3. 移动坐标原点(将坐标原点从左上角移动到右下角)

    painter.translate(-this->geometry().width(), -this->geometry().height());
    

    在这里插入图片描述

  4. 绘制图像

    painter.drawPixmap(20, 20, 800, 600, map);
    

    在这里插入图片描述

  5. 恢复坐标系状态

    painter.restore();
    
http://www.dtcms.com/a/350999.html

相关文章:

  • 无人机三维路径规划首选算法:RRT_
  • 基于大模型的智能占卜系统实战-Qwen-VL、RAG、FastAPI
  • 【算法--链表题1】2. 两数相加:通俗详解
  • Linux系统网络管理学习.2
  • Spring面试题及详细答案 125道(26-45) -- Spring AOP篇
  • PLC通讯中遇到的实际场景
  • 8.25作业
  • 管家婆工贸ERP BB116.销售订单选存货
  • 视觉语言模型(VLM)
  • 动态带宽扩展(DBE):下一代Wi-Fi性能提升的关键技术
  • 《计算机视觉度量:从特征描述到深度学习》-- 大模型特征提取到特征检索
  • 身份管理与安全 (Protect identities)
  • 一文丝滑使用Markdown:从写作、绘图到转换为Word与PPT
  • HIDL的Car Audio架构简单梳理
  • Spark 节点 IDO 正式开启 —引领 PayFi 新时代
  • 解析蛋白质三维结构-Bio3D R包
  • Elasticsearch精准匹配与全文检索对比
  • 矩阵微积分的链式法则(chain rule)
  • 一步一步在Kubernetes集群部署NVIDIA KAI Scheduler
  • 数据挖掘 7.1~7.4 Clustering聚类
  • Spark云原生流处理实战与风控应用
  • 【贪心】11 盛最多水的容器(双指针解法)
  • 解决Windows更新后WPF程序报TypeLoadException异常的问题
  • 论文Review 激光3DGS GS-SDF | IROS2025 港大-MARS!| 激光+3DGS+NeRF会得到更好的几何一致性和渲染结果!?
  • OceanStor Pacific 9926全闪分布式存储,海量数据大容量场景的救星来咯[特殊字符]!
  • 列表里的对象,按对象的某个属性值排序
  • 如何利用ArcGIS探究环境与生态因子对水体、土壤、大气污染物等影响实践技术
  • 深入了解linux系统—— 线程互斥
  • 软件开发|Shiro框架以及集成Spring Boot
  • AI算力提升7.5倍!英伟达发布新一代机器人超级计算机Jetson Thor,驱动物理AI革命