Qt——界面优化
一.QSS
1.背景
在网页前端开发领域中, CSS 是⼀个至关重要的部分。 描述了⼀个网页的 "样式"。 从而起到对网页美化的作用。 所谓样式,包括不限于大小,位置,颜色,背景,间距,字体等等。
Qt 仿照 CSS 的模式, 引入了 QSS, 来对 Qt 中的控件做出样式上的设定, 从而允许程序猿写出界面更好看的代码。
如果通过 QSS 设置的样式和通过 C++ 代码设置的样式冲突, 则 QSS 优先级更高。
2.基本语法
选择器 {
属性名: 属性值;
}
其中:
- 选择器 描述了 "哪个 widget 要应用样式规则".
- 属性 则是⼀个键值对, 属性名表示要设置哪种样式, 属性值表示了设置的样式的值.
例如:
QPushButton { color: red; }
表示针对界面上的所有 QPUshButten ,都把文字的颜色设置为红色。
3.选择器
QSS 的选择器⽀持以下几种:
全局选择器,如:*:选择所有的 widget.
类型选择器,如:QPushButton :选择所有的 QPushButton 和 其子类的控件.
类选择器,如: .QPushButton :选择所有的 QPushButton 的控件,不会选择子类.
ID 选择器,如:#pushButton_2 :选择 objectName 为 pushButton_2 的控件.
后代选择器,如:QDialog QPushButton :选择 QDialog 的所有后代(子控件, 孙子控件等等)中的 QPushButton.
子选择器,如:QDialog > QPushButton :选择 QDialog 的所有子控件中的 QPushButton.
并集选择器,如:QPushButton, QLineEdit, QComboBox :选择 QPushButton, QLineEdit, QComboBox 这三种控件. (即接下来的样式会针对这三种控件都生效).
属性选择器,如:QPushButton[flat="false"] :选择所有 QPushButton 中, flat 属性为 false 的控件.
(1)子控件选择器
有些控件的内部包含多个子控件,例如QComboBox 的下拉后的面板, QSpinBox 的上下按钮等。

这样的子控件也是可以设置其样式的,可以通过子控件选择器“::” , 针对上述子控件进行样式设置。例如下拉框的下拉按钮就可以通过子控件选择器QComboBox::down-arrow来选中。
更多的子控件,还请自行查询Qt文档来进行了解。

(2)伪类选择器
伪类选择器, 是根据控件所处的某个状态被选择的. 例如按钮被按下, 输入框获取到焦点, 鼠标移动到某个控件上等.
当状态具备时, 控件被选中,样式生效。当状态不具备时,控件不被选中,样式失效。
使用“:”的方式定义伪类选择器。
常用的伪类选择器有:
:hover :鼠标放到控件上
:pressed :鼠标左键按下时
:focus :获取输入焦点时
:enabled :元素处于可用状态时
:checked :被勾选时
:read-only :元素为只读状态时
这些状态可以使用 ! 来取反,比如 :!hover 就是鼠标离开控件时, :!pressed 就是鼠标松开。
4.基本使用
(1)设置单独控件样式
设置控件的颜色,可以使用如下接口:
setStyleSheet(
选择器 {
属性名: 属性值;
}
);
例如,设置按钮1的文本颜色为红色:
ui->pushButton->setStyleSheet("QPushButton {color : red}");
结果如下:

能够看出,按钮1的文本被设置为红色了,通过此种方法,可以将选择的单独的控件设置颜色。
除了为单独的控件设置之外,还可以同时对界面中的多个相同控件一起设置颜色:
this->setStyleSheet("QPushButton {color : red}");
this表示整个widget界面,如此代码,就是将整个界面中的所有按钮控件的文本颜色都设置的红色,结果如下:

(2)设计全局样式
我们希望将某些控件的样式放在一起管理,而不是单独的分散的设置,则可以在main函数中进行设置:

结果如下:

设置全局样式之后,如果需要对个别的控件进行局部微调,则可以在widget.cpp中设置:
ui->pushButton->setStyleSheet("QPushButton {color : green}");
ui->pushButton_2->setStyleSheet("QPushButton {font-size : 50px}");
例如将按钮1颜色改为绿色,按钮2的像素改为50px,结果如下:

能够看出,如果控件的样式冲突,则局部设置的优先级高于全局,如果样式不冲突,则不同的样式可以层叠。
(3)样式与代码分离
上述设置样式的方式,都是耦合在代码之中,这样的方式显然是有弊端的,因此我们希望能够将样式的设置与代码进行分离,Qt Designer中集成了这样的功能,允许将样式写入.ui文件中:

在整个大widget控件上选择改变样式表,在样式表中设置样式:

就可以直接应用到整个ui上:

如果想要改变某个控件的样式,就右键点击该控件,同样选择改变样式表,就可以为该单独的控件设置样式。

这里将按钮2单独设置为绿色。
除此之外,还可以通过在当前目录中新建一个.qss文件,在该文件中编辑样式,再将该文件导入.qrc文件中,最后通过文件操作读取样式进行设置。
无论是通过哪种方式来设置样式,都建议不要混用多种方式,一种方式用到底,以免出现问题时难以查找到问题所在。
5.盒子模型

一个控件也是有其内部的独立结构模型的,⼀个遵守盒模型的控件, 由上述几个部分构成:
-
Content 矩形区域: 存放控件内容. 比如包含的文本/图标等.
-
Border 矩形区域: 控件的边框.
-
Padding 矩形区域: 内边距. 边框和内容之间的距离.
-
Margin 矩形区域: 外边距. 边框到控件 geometry 返回的矩形边界的距离
默认情况下, 外边距, 内边距, 边框宽度都是 0.
可以通过⼀些 QSS 属性来设置上述的边距和边框的样式。
margin :设置四个方向的外边距. 复合属性.
padding:设置四个方向的内边距. 复合属性.
border-style:设置边框样式
border-width:边框的粗细
border-color:边框的颜色
border:复合属性, 相当于 border-style + border-width + border-color
下面用一个例子来具体设置一下一个控件的盒子模型样式:

这里我们用代码方式创建了一个按钮控件,并且将它的位置放在左上角,下面来设置它的内外边距和边框样式:
button->setStyleSheet("QPushButton {border : 10px solid red; margin: 20px; padding: 5px;}");
将边框设置为10px,实线,红色,外边距为20px,内边距为5像素,结果如下:

不难看出,整个按钮的大小尺寸仍未100×100,外边距表示边框与控件初始大小范围的间距,内边距则表示边框与控件内容之间的间距。
二.绘图API
1.基本概念
虽然 Qt 已经内置了很多的控件, 但是不能保证现有控件就可以应对所有场景。
很多时候我们需要更强的 "自定制" 能力。
Qt 提供了画图相关的 API, 可以允许在窗口上绘制任意的图形形状, 来完成更复杂的界面设计。
绘图 API 核心类
QPainter:"绘画者". 用来绘图的对象, 提供了⼀系列 drawXXX 方法, 可以允许我们绘制各种图形.
QPaintDevice:"画板". 描述了 QPainter 把图形画到哪个对象上. 像之前用过的 QWidget 也是⼀种 QPaintDevice (QWidget 是 QPaintDevice 的子类) .
QPen:"画笔". 描述了 QPainter 画出来的线是什么样的.
QBrush:"画刷". 描述了 QPainter 填充⼀个区域是什么样的.
绘图 API 的使用, 一般不会在 QWidget 的构造函数中使用, 而是要放到 paintEvent 事件中.
paintEvent 会在以下情况下被触发:
- 控件首次创建.
- 控件被遮挡, 再解除遮挡.
- 窗口最小化, 再恢复.
- 窗口最大化, 再恢复.
- 控件大小发生变化时.
- 主动调用 repaint() 或者 update() 方法. (这两个方法都是 QWidget 的方法).
因此, 如果把绘图 api 放到构造函数中调用, 那么⼀旦出现上述的情况, 界⾯的绘制效果就无法确保符合预期了。
2.绘制各种形状
首先需要在widget.h文件中声明事件函数:
void paintEvent(QPaintEvent* event);
之后在widget.cpp文件中定义事件函数:
void Widget::paintEvent(QPaintEvent *event)
{(void) event;//创建绘图对象QPainter painter(this);//绘制线段painter.drawLine(0,50,200,50);//绘制矩形painter.drawRect(100,100,150,150);//绘制圆形painter.drawEllipse(250,250,300,300);
}
这些函数的参数表示各不相同:
- 对于线段:前两个表示起点坐标,后两个表示终点坐标。
- 对于矩形:前两个表示矩形左上角所处位置,后两个表示所绘矩形的长度和宽度。
- 对于圆形:圆形的这四个坐标表示其外接矩阵的构建方式,通过其外接矩阵来构建圆形。
结果如下:

上述绘制的图形都是其最基础的样式,如果想要改变其样式,则需要通过QPen 画笔对象来实现:
void Widget::paintEvent(QPaintEvent *event)
{(void) event;//创建绘图对象QPainter painter(this);//创建画笔对象QPen pen;pen.setColor("red");painter.setPen(pen);//绘制圆形painter.drawEllipse(100,100,300,300);
}
例如将圆的颜色设置为红色,结果如下:

除此之外,还可以设置图形的填充颜色,通过QBrush对象实现:
void Widget::paintEvent(QPaintEvent *event)
{(void) event;//创建绘图对象QPainter painter(this);//创建画笔对象QPen pen;pen.setColor("red");painter.setPen(pen);//创建画刷对象QBrush brush;brush.setColor("green");//设置实心填充brush.setStyle(Qt::SolidPattern);painter.setBrush(brush);//绘制圆形painter.drawEllipse(100,100,300,300);
}
例如将圆的内部实心填充为绿色:

画刷的填充方式有很多,具体可以查询Qt文档获取。
相关文章:
Qt——界面优化
一.QSS 1.背景 在网页前端开发领域中, CSS 是⼀个至关重要的部分。 描述了⼀个网页的 "样式"。 从而起到对网页美化的作用。 所谓样式,包括不限于大小,位置,颜色,背景,间距,字体等等…...
MySQL 数据库常见字段类型大全及详细解析
在工作期间会遇到数据库建表的业务,经常会使用复制粘帖等操作,而不清楚数据库的字段类型。本文记录了 MySQL 数据库常见字段类型,根据不同的数据需求,可以选择不同的字段类型来存储数据。 文章目录 一、整数类型1、TINYINT&#x…...
MATLAB 工具库的使用说明和案例示例
以下是一些常见的 MATLAB 工具库的使用说明和案例示例: 信号处理工具箱(Signal Processing Toolbox): 使用说明:提供了用于生成、测量、变换、过滤和可视化信号的函数和应用程序。包括重新采样、平滑、同步信号、设计…...
对于Docker的初步了解
简介与概述 1.不需要安装环境,工具包包含了环境(jdk等) 2.打包好,“一次封装,到处运行” 3.跨平台,docker容器在任何操作系统上都是一致的,这就是实现跨平台跨服务器。只需要一次配置好环境&…...
java基础学习——jdbc基础知识详细介绍
引言 数据的存储 我们在开发 java 程序时,数据都是存储在内存中的,属于临时存储,当程序停止或重启时,内存中的数据就会丢失,我们为了解决数据的长期存储问题,有以下解决方案: 通过 IO流书记&…...
第20篇:Python 开发进阶:使用Django进行Web开发详解
第20篇:使用Django进行Web开发 内容简介 在上一篇文章中,我们深入探讨了Flask框架的高级功能,并通过构建一个博客系统展示了其实际应用。本篇文章将转向Django,另一个功能强大且广泛使用的Python Web框架。我们将介绍Django的核…...
CukeTest使用 | 1 CukeTest是什么?如何下载安装?
CukeTest使用 | 1 CukeTest是什么?如何下载安装? 1 CukeTest是什么?2 关于开发者3 CukeTest有哪些特性?4 都支持哪些自动化技术类型?5 版本区别6 下载安装 特殊说明:学习内容主要来自官网的教程、以及网上公…...
An OpenGL Toolbox
3.An OpenGL Toolbox 声明:该代码来自:Computer Graphics Through OpenGL From Theory to Experiments,仅用作学习参考 3.1 Vertex Arrays and Their Drawing Commands 顶点数组及其绘制命令:将几何数据存储在一个位置,…...
R语言学习笔记之高效数据操作
一、概要 数据操作是R语言的一大优势,用户可以利用基本包或者拓展包在R语言中进行复杂的数据操作,包括排序、更新、分组汇总等。R数据操作包:data.table和tidyfst两个扩展包。 data.table是当前R中处理数据最快的工具,可以实现快…...
构造函数及实例化的过程:实例成员
构造函数:是一种特殊的函数,主要用来初始化对象 使用场景:比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一遍,此时可以通过构造函数来快速创建多个类似的对象。 构造函数语法:大写字母开头的函数 function Pig(name,age,gender)…...
Linux的权限和一些shell原理
目录 shell的原理 Linux权限 sudo命令提权 权限 文件的属性 ⽂件类型: 基本权限: chmod改权限 umask chown 该拥有者 chgrp 改所属组 最后: 目录权限 粘滞位 shell的原理 我们广义上的Linux系统 Linux内核Linux外壳 Linux严格…...
LearnOpenGL——光照
教程地址:简介 - LearnOpenGL CN 前言 这篇开始光照的学习。 颜色 原文链接: 颜色 - LearnOpenGL CN总结: 重新搭建了一个简单场景,为后面的学习做准备。 现实世界中有无数种颜色,每一个物体都有它们自己的颜色。我…...
落地 ORB角点检测与sift检测
ORB角点检测 可以说ORB是由FAST、灰度质心和BRIEF等技术组合优化形成的,不过更准确地说,ORB是在FAST特征检测算法基础上,结合了灰度质心确定方向以及改进后的BRIEF描述子等技术形成的,以下是具体分析: • FAST特征检…...
步入响应式编程篇(二)之Reactor API
步入响应式编程篇(二)之Reactor API 前言回顾响应式编程Reactor API的使用Stream引入依赖Reactor API的使用流源头的创建 reactor api的背压模式发布者与订阅者使用的线程查看弹珠图查看形成新流的日志 前言 对于响应式编程的基于概念,以及J…...
利用Redis实现数据缓存
目录 1 为啥要缓存捏? 2 基本流程(以查询商铺信息为例) 3 实现数据库与缓存双写一致 3.1 内存淘汰 3.2 超时剔除(半自动) 3.3 主动更新(手动) 3.3.1 双写方案 3.3.2 读写穿透方案 3.3.…...
如何使用 pytest-html 创建自定义 HTML 测试报告
关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 测试 Python 代码对于提高代码质量、检测漏洞或意外行为至关重要。 但测试结果又该…...
服务器中的流量主要是指什么?
服务器流量就是指服务器在单位时间内所传输的数据量,服务器流量在互联网中起着十分重要的作用,一般会被用来处理网站的访问请求,当用户在网站中浏览网页和视频时,服务器会接收到用户的请求,同时会返回网站的内容。 服务…...
飞牛NAS安装过程中的docker源问题
采用CloudFlare进行飞牛NAS的远程访问 【安全免费】无需公网IP、端口号,NAS外网访问新方法_网络存储_什么值得买 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://docker.1panel.dev&quo…...
【动态规划】--- 斐波那契数模型
Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: 算法Journey 🏠 第N个泰波那契数模型 📌 题目解析 第N个泰波那契数 题目要求的是泰波那契数,并非斐波那契数。 &…...
php-phar打包避坑指南2025
有很多php脚本工具都是打包成phar形式,使用起来就很方便,那么如何自己做一个呢?也找了很多文档,也遇到很多坑,这里就来总结一下 phar安装 现在直接装yum php-cli包就有phar文件,很方便 可通过phar help查看…...
ChirpIoT技术的优势以及局限性
ChirpIoT是一种由上海磐启微电子开发的国产无线射频通讯技术,ChirpIoT技术基于磐启多年对雷达等线性扩频信号的深入研究,并在此基础上对线性扩频信号的变化进行了改进,实现了远距离传输的一种无线通信技术。相关产品型号有E29-400T22D、E290-…...
java提取系统应用的日志中的sql获取表之间的关系
为了获取到对应的sql数据,分了三步骤 第一步,获取日志文件,解析日志文件中的查询sql,递归解析sql,获取表关系集合 递归解析sql,获取表与表之间的关系 输出得到的对应关联关系数据 第二步,根据获…...
PyQt6医疗多模态大语言模型(MLLM)实用系统框架构建初探(下.代码部分)
医疗 MLLM 框架编程实现 本医疗 MLLM 框架结合 Python 与 PyQt6 构建,旨在实现多模态医疗数据融合分析并提供可视化界面。下面从数据预处理、模型构建与训练、可视化界面开发、模型 - 界面通信与部署这几个关键部分详细介绍编程实现。 6.1 数据预处理 在医疗 MLLM 框架中,多…...
IMX6ull项目环境配置
文件解压缩: .tar.gz 格式解压为 tar -zxvf .tar.bz2 格式解压为 tar -jxvf 2.4版本后的U-boot.bin移植进SD卡后,通过串口启动配置开发板和虚拟机网络。 setenv ipaddr 192.168.2.230 setenv ethaddr 00:04:9f:…...
Linux(Centos 7.6)命令详解:wc
1.命令作用 打印文件的行数、单词数、字节数,如果指定了多个文件,还会打印以上三种数据的总和(Print newline, word, and byte counts for each FILE, and a total line if more than one FILE is specified) 2.命令语法 Usage: wc [OPTION]... [FIL…...
Gradle buildSrc模块详解:集中管理构建逻辑的利器
文章目录 buildSrc模块二 buildSrc的使命三 如何使用buildSrc1. 创建目录结构2. 配置buildSrc的构建脚本3. 编写共享逻辑4. 在模块中引用 四 典型使用场景1. 统一依赖版本管理2. 自定义Gradle任务 3. 封装通用插件4. 扩展Gradle API 五 注意事项六 与复合构建(Compo…...
六、深入了解DI
依赖注入是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象. 在上⾯程序案例中,我们使⽤了 Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中。 关于依赖注…...
基于RAG构建Text2SQL的实战教程
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…...
【论文阅读】HumanPlus: Humanoid Shadowing and Imitation from Humans
作者:Zipeng Fu、Qingqing Zhao、Qi Wu、Gordon Wetstein、Chelsea Finn 项目共同负责人,斯坦福大学 项目网址:https://humanoid-ai.github.io 摘要 制造外形与人类相似的机器人的一个关键理由是,我们可以利用大量的人类数据进行…...
第25篇 基于ARM A9处理器用C语言实现中断<一>
Q:怎样理解基于ARM A9处理器用C语言实现中断的过程呢? A:同样以一段使用C语言实现中断的主程序为例介绍,和汇编语言实现中断一样这段代码也使用了定时器中断和按键中断。执行该主程序会在DE1-SoC的红色LED上显示流水灯…...
