【Qt界面优化】—— QSS 的介绍

news2024/11/16 17:16:52

目录

(一)背景介绍

(二)基本语法 

 (三)QSS设置方式

3.1 指定控件样式设置

3.2 全局样式设置 

3.3 使用Qt Designer编辑样式 

(四)选择器 

4.1 选择器概况

4.2 子控件选择器(Sub-Controls)

4.3 伪类选择器(Pseudo-States)

(五)样式属性

5.1 盒模型(BoxModel)

(六)控件样式示例

6.1 按钮

6.2 复选框 

总结


(一)背景介绍

在网页前端开发领域中,CSS是⼀个至关重要的部分.描述了⼀个网页的"样式".从起到对网页美化的 作用。

  • 所谓样式,包括不限于大小,位置,颜色,背景,间距,字体等等.

  • 现在的网页很难找到没有CSS的.可以说让"界面好看"是⼀个刚需. 

"好看"这个事情有没有意义呢?是否⼀个软件,能满足核心功能即可,界面好看无所谓呢? 参考知乎上的这个帖子:https://www.zhihu.com/question/30918916/answer/49934463 

  •  网页开发作为GUI的典型代表,也对于其他客户端GUI开发产⽣了影响.Qt也是其中之⼀.

Qt 仿照CSS的模式,引入了QSS,来对Qt中的控件做出样式上的设定,从而允许程序猿写出界面更好看的代码.

  • 同样受到HTML的影响,Qt还引⼊了QML来描述界面,甚至还可以直接把⼀个原生的html页面加载到界面上.这部分内容这里不做讨论.

当然,由于Qt本身的设计理念和网页前端还是存在⼀定差异的,因此QSS中只能支持部分CSS属性. 整体来说QSS要比CSS更简单⼀些. 

注意: 如果通过QSS设置的样式和通过C++代码设置的样式冲突,则QSS优先级更⾼


(二)基本语法 

对于CSS来说,基本的语法结构非常简单.

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

QSS沿用户了这样的设定.

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

其中:

  1. 选择器描述了"哪个widget要应用样式规则".
  2. 属性则是⼀个键值对,属性名表示要设置哪种样式,属性值表示了设置的样式的值.

例如:

QPushButton { color: red; }

 或者

QPushButton {
    color: red;
}
  • 上述代码的含义表示,针对界面上所有的QPushButton,都把文本颜色设置为 “红色”

代码示例:

1) 在界面上创建⼀个按钮.

2) 编写代码,设置样式 

Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
 {
     ui->setupUi(this);
     ui->pushButton->setStyleSheet("QPushButton { color: red; }");
 }

3) 运行程序,观察效果.可以看到文本已经是红色了.

  • 上述代码中,我们是只针对这⼀个按钮通过 setStyleSheet 方法设置的样式.此时这个样式 仅针对该按钮生效.如果创建其他按钮,其他按钮不会受到影响. 

 (三)QSS设置方式

3.1 指定控件样式设置

QWidget 中包含了 setStyleSheet 方法,可以直接设置样式. 上述代码我们已经演示了上述设置方式.

另⼀方面,给指定控件设置样式之后,该控件的子元素也会受到影响.


代码示例:

1) 在界面上创建⼀个按钮

2) 修改widget.cpp,这次我们不再给按钮设置样式,而是给Widget设置样式(Widget是 QPushButton的父控件). 

Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
     ui->setupUi(this);
     // 给Widget 本⾝设置样式
     this->setStyleSheet("QPushButton { color: red;} ");
}

3) 运行程序,可以看到样式对于子控件按钮同样会生效.


3.2 全局样式设置 

还可以通过 QApplication 的 setStyleSheet 方法设置整个程序的全局样式.

全局样式优点:

  • 使同⼀个样式针对多个控件生效,代码更简洁.
  • 所有控件样式内聚在⼀起,便于维护和问题排查.

代码示例:

1) 在界面上创建三个按钮.

2) 编辑main.cpp,设置全局样式 

int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     //设置全局样式
 
     a.setStyleSheet("QPushButton { color: red; }");

     Widget w;
     w.show();
     return a.exec();
}

3) 运行程序,可以看到此时三个按钮的颜色都设置为红色了.


代码示例:样式的层叠特性

如果通过全局样式给某个控件设置了属性1,通过指定控件样式给控件设置属性2,那么这两个属性都会产生作用.

1) 在界面上创建两个按钮

2) 编写main.cpp,设置全局样式,把按钮文本设置为红色. 

int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     // 设置全局样式
 
     a.setStyleSheet("QPushButton { color: red; }");

     Widget w;
     w.show();
     return a.exec();
}

3) 编写widget.cpp,给第⼀个按钮设置字体大小

Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
     ui->setupUi(this);

     //设置指定控件样式
     ui->pushButton->setStyleSheet("QPushButton { font-size: 50px} ");

}

4) 运行程序,可以看到,对于第⼀个按钮来说,同时具备了颜色和字体大小样式.而第⼆个按钮只有颜色样式.

  • 说明针对第⼀个按钮,两种设置方式设置的样式,叠加起来了.

  • 形如上述这种属性叠加的效果,我们称为"层叠性".
  • CSS全称为CascadingStyleSheets,其中Cascading就是"层叠性"的意思QSS也继承了这 样的设定.
  • 实际上把QSS叫做QCSS也许更合适⼀些~ 

3.3 使用Qt Designer编辑样式 

QSS也可以通过QtDesigner直接编辑,从而起到实时预览的效果.同时也能避免C++和QSS代码的耦合.

代码示例:使用Qt Designer编辑样式

1) 在界面上创建⼀个按钮

2) 右键按钮,选择"改变样式表" 

3) 在弹出的样式表编辑器中,可以直接填写样式.填写完毕,点击OK即可. 

4) 此时QtDesigner的预览界面就会实时显示出样式的变化. 

5) 运行程序,可以看到样式确实发生了改变. 

这种方式设置样式,样式内容会被以xml格式记录到ui文件中. 

<property name="styleSheet">
<string notr="true">QPushButton { color: red; }</string>
</property>

同时在控件的 styleSheet 属性中也会体现.

当我们发现⼀个控件的样式不符合预期的时候,要记得排查这四个地方:

  • 全局样式
  • 指定控件样式
  • qss文件中的样式
  • ui文件中的样式 

(四)选择器 

4.1 选择器概况

QSS的选择器支持以下几种:

  •  总体来说,QSS选择器的规则和CSS选择器基本⼀致.
  • 上述选择器咱们也不需要全都掌握,就只熟悉最常用的几个即可(上述加粗的).

代码示例:使用类型选择器选中子类控件

1) 在界面上创建⼀个按钮.

2) 修改main.cpp,设置全局样式 

  • 注意,此处选择器使用的是QWidget . QPushButton也是QWidget 的子类,所以会到, QWidget 选择器的影响
int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     //设置全局样式
 
     a.setStyleSheet("QWidget { color: red; }");

     Widget w;
     w.show();
     return a.exec();
}

3) 运行程序,可以看到按钮的文本颜色已经是红色了.

5) 如果把上述样式代码修改为下列代码 

a.setStyleSheet(".QWidget { color: red; }");
  • 此时按钮的颜⾊不会发生改变.此时只是选择 QWidget 了. 而不会选择 QWidget 的子类QPushButton


4.2 子控件选择器(Sub-Controls)

 

有些控件内部包含了多个"子控件".比如QComboBox的下拉后的面板,比如QSpinBox的上下按钮等.

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

代码示例:设置下拉框的下拉按钮样式

1) 在界面上创建⼀个下拉框,并创建几个选项

2) 创建 resource.qrc ,并导入图片 down.png 

3) 修改main.cpp,编写全局样式

  • 使用子控件选择器 QComboBox::down-arrow 选中了
  • 再通过 image 属性设置图片. 
int main(int argc, char *argv[])
{
     QApplication a(argc, argv);

     QString style = "";
     style += "QComboBox::down-arrow { image: url(:/down.png) }";
     a.setStyleSheet(style);

     Widget w;
     w.show();
     return a.exec();
}

4) 执行程序,观察效果 


4.3 伪类选择器(Pseudo-States)

伪类选择器,是根据控件所处的某个状态被选择的.例如按钮被按下,输入框获取到焦点,⿏标移动到某 个控件上等.

  • 当状态具备时,控件被选中,样式生效.
  • 当状态不具备时,控件不被选中,样式失效. 

使用 : 的方式定义伪类选择器.

常用的伪类选择器

 这些状态可以使用 !来取反.比如 :!hover 就是⿏标离开控件时, :!pressed 就是⿏标松开时,等等.


(五)样式属性

QSS中的样式属性非常多,不需要都记住.核心原则还是用到了直接去查. 大部分的属性和CSS是非常相似的。(文档的 Qt Style Sheets Reference 章节详细介绍了哪些控件可以设置属性,每个控件都能设置哪些属性等.

5.1 盒模型(BoxModel)

在文档的Customizing Qt Widgets Using Style Sheets 的 The Box Model 章节介绍了盒模型.

⼀个遵守盒模型的控件,由上述几个部分构成.

  • Content 矩形区域:存放控件内容.比如包含的文本/图标等.
  • Border 矩形区域:控件的边框.
  • Padding 矩形区域:内边距.边框和内容之间的距离.
  • Margin 矩形区域:外边距.边框到控件

默认情况下,外边距,内边距,边框宽度都是0.

可以通过⼀些QSS属性来设置上述的边距和边框的样式.


代码示例:设置边框和内边距 

 1) 在界面上创建⼀个label

2) 修改main.cpp,设置全局样式 

int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     a.setStyleSheet("QLabel { border: 5px solid red; padding-left: 10px; }");

     Widget w;
     w.show();
     return a.exec();
}

3) 运行程序,可以看到样式发生了变化

 


(六)控件样式示例

下⾯给出⼀些常⽤控件的样式示例.

6.1 按钮

代码示例:自定义按钮

1) 界面上创建⼀个按钮

2) 右键->改变样式表,使用QtDesigner设置样式

QPushButton {
     font-size: 20px;
     border: 2px solid #8f8f91;
     border-radius: 15px;
     background-color: #dadbde;
}
QPushButton:pressed {
     background-color: #f6f7fa;
}

3) 执行程序,可以看到效果

 


代码示例:设置外边距

为了方便确定控件位置,演示外边距效果,我们使用代码创建⼀个按钮.

1) 修改widget.cpp,创建按钮,并设置样式.

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

2) 运行程序,可以看到,当前按钮的边框被外边距挤的缩小了.但是获取到的按钮的的. Geometry 是不变


6.2 复选框 

代码示例:自定义复选框

1) 创建⼀个 resource.qrc 文件,并导入以下图片.

使用黑色作为默认形态. 使用黑色作为hover形态. 使用红色作为pressed形态. 

2) 创建⼀个复选框 

3) 编辑复选框的样式

QCheckBox {
     font-size: 20px;
}
QCheckBox::indicator {
     width: 20px;
     height: 20px;
}
QCheckBox::indicator:unchecked {
     image: url(:/checkbox-unchecked.png);
}
QCheckBox::indicator:unchecked:hover {
     image: url(:/checkbox-unchecked_hover.png);
}
QCheckBox::indicator:unchecked:pressed {
     image: url(:/checkbox-unchecked_pressed.png);
}
QCheckBox::indicator:checked {
     image: url(:/checkbox-checked.png);
}
QCheckBox::indicator:checked:hover {
     image: url(:/checkbox-checked_hover.png);
}
QCheckBox::indicator:checked:pressed {
     image: url(:/checkbox-checked_pressed.png);
}

4) 运行程序,可以看到此时的复选框就变的丰富起来了.


除了上述之外,还有包括像单选框、列表、输入框等各种控件,在这里就不一一演示了!! 


总结

QSS本身给Qt提供了更丰富的样式设置的能力,但是整体来说QSS的功能是不如CSS的.

在CSS中,整个网页的样式,都是CSS一手负责,CSS功能更强大,并且也更可控.

相⽐之下,Qt中是以原生api为主,来控制控件之间的尺寸,位置等,QSS只是起到辅助的作用.

而且Qt中提供的⼀些"组合控件"(像QComboBox,QSpinBox等)内部的结构是不透明的,此时进行⼀ 些样式设置也会存在⼀定的局限性.

另外,做出好看的界面,光靠QSS是不够的.更重要的是需要专业美工做出设计稿.这里主要是了解这个技术

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2137246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

石英砂酸洗废酸处理

石英砂酸洗废酸处理是一个复杂而精细的过程&#xff0c;旨在将酸洗过程中产生的废酸中的有害物质去除&#xff0c;使其达到环保排放标准或实现资源化利用。以下是对该处理工艺方法的详细阐述&#xff1a; 一、废酸收集与调节 废酸收集&#xff1a;首先&#xff0c;将酸洗石英砂…

10年Python程序员教你多平台采集10万+电商数据【附实例】

10万级电商数据采集需要注意什么&#xff1f; 在进行10万级电商数据采集时&#xff0c;有许多关键因素需要注意&#xff1a; 1. 采集平台覆盖&#xff1a;确保可以覆盖主流的电商平台&#xff0c;如淘宝、天猫、京东、拼多多等。 2. 数据字段覆盖&#xff1a;检查是否可以对平…

Java多线程面试精讲:源于技术书籍的深度解读

写在前面 ⭐️在无数次的复习巩固中&#xff0c;我逐渐意识到一个问题&#xff1a;面对同样的面试题目&#xff0c;不同的资料来源往往给出了五花八门的解释&#xff0c;这不仅增加了学习的难度&#xff0c;还容易导致概念上的混淆。特别是当这些信息来自不同博主的文章或是视…

JDBC初相识

文章目录 JDBC的由来JDBC的好处 JDBC核心API的介绍JDBC会用到的包JDBC四个核心对象JDBC访问数据库的步骤 客户端操作MySQL数据库的方式 使用第三方客户端来访问MySQL&#xff1a;SQLyog、Navicat 使用MySQL自带的命令行方式 通过Java来访问MySQL数据库&#xff0c;今天要学习…

HighCharts图表自动化简介

什么是分析数据? 在任何应用程序中捕获并以图形或图表形式显示的分析数据是任何产品或系统的关键部分,因为它提供了对实时数据的洞察。 验证此类分析数据非常重要,因为不准确的数据可能会在报告中产生问题,并可能影响应用程序/系统的其他相关领域。 什么是HighChart? …

Spring IOC的应用

目录 一、IOC基础 1、maven导入spring的 jar包 和 单测包 2、bean的配置 2.1 纯xml模式 2.1.1 xml文件头 2.1.2 实例化Bean的三种方式 2.1.3 Bean的生命周期 2.1.4 Bean标签属性 2.1.5 DI依赖注入的xml配置 2.1.5.1 构造函数注入 2.1.5.2 set方法注入 2.1.5.3 复杂数据类型注入…

纯血鸿蒙NEXT常用的几个官方网站

一、官方文档 https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/Readme-CN.md刚入门查看最多的就是UI开发模块&#xff0c;首先要熟悉组件使用 二、官方API参考 https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/development-i…

Python数据分析 Pandas库-初步认识

Python数据分析 Pandas库-初步认识 认识Pandas ​ pandas是一个非常实用的Python工具&#xff0c;我们可以把它想象成一个超级强大的表格处理工具&#xff0c;它比Excel更智能&#xff0c;操作更为简单。pands可以从各种文件格式&#xff08;CSV、JSON、SQL、Excel&#xff0…

同时拥有独显和核显,怎么让应用程序选择使用哪个GPU?

看你现在使用的是核显还是独显 勾选上GPU引擎选项&#xff0c;后面便会标识你所使用的是哪种显卡&#xff0c;如果是独立显卡&#xff0c;就可以免去后续的操作&#xff1b;如果不是&#xff0c;那么请继续接下来的操作。 将你需要使用独显的程序换成gpu1&#xff08;独显&am…

『功能项目』怪物的有限状态机【42】

本章项目成果展示 我们打开上一篇41项目优化 - 框架加载资源的项目&#xff0c; 本章要做的事情是按照框架的思想构建项目并完成怪物的自动巡逻状态&#xff0c;当主角靠近怪物时&#xff0c;怪物会朝向主角释放技能 首先新建脚本&#xff1a;BossCtrl.cs (通常把xxxCtrl.cs脚…

【Unity】Unity Shader样例:顶点根据时间放大缩小

文章目录 案例说明效果展示适用模型范围代码示例 案例说明 本案例提供一个单独的Shader&#xff0c;使得模型顶点&#xff08;仅渲染&#xff09;根据时间放大缩小&#xff0c;往复循环。 效果展示 适用模型范围 全部 代码示例 Shader "Unlit/Sha_TestScale" {P…

Multiscale Vision Transformers(MViT)

Multiscale Vision Transformers 多尺度视觉Transformer (MViT) 是一种新型的视觉识别模型&#xff0c;主要用于处理图像和视频。它结合了传统多尺度特征层次结构与Transformer模型的优势&#xff0c;旨在提高视频和图像的识别性能。 1. 多尺度视觉Transformer (MViT) 的概念…

数据可视化与分析:数据时代的关键工具

一、引言 数据可视化与分析是大数据时代中最为重要的技术之一。随着数据量的不断增加&#xff0c;如何有效地理解、解释和利用数据&#xff0c;已经成为各行各业面临的关键挑战。数据可视化通过图表、图形和互动界面将数据以直观的方式呈现&#xff0c;帮助用户快速识别数据中…

运行QWen2-1.5b模型时报错“RuntimeError: cutlassF: no kernel found to launch!”

运行QWen2-1.5b模型时报错“RuntimeError: cutlassF: no kernel found to launch!” #问题&#xff1a;成功加载QWen2-1.5b模型&#xff0c;但是推理时 “model.generate( model_inputs.input_ids, top_pself.top_p, max_new_tokens512 )时”&#xff0c;报错“RuntimeError: …

TCP客户端编码和解码处理:发送和接收指定编码消息

文章目录 引言基于Netty实现TCP客户端Netty发送GBK编码指令Netty接收GBK编码基于Channel发送指令基于ChannelHandlerContext发送指令:建立连接时发送登陆指令开启日志,查看报文信息基于ChannelInboundHandlerAdapter进行业务逻辑处理原生API实现TCP客户端基于DataOutputStrea…

vue2制作高复用页面

记录一下页面搭建记录&#xff0c;利用vue2组件化开发的思想。这个页面适合于大部分信息管理系统~。模板固定&#xff0c;每次使用&#xff0c;直接修改表单表格参数&#xff0c;api接口等。 以上图页面为例&#xff0c;一个基础数据信息页面可以分为&#xff0c;分类&#xff…

数据恢复软件推荐:轻松找回删除的文件!

在使用电脑的过程中&#xff0c;有时我们会误操作或者因为其他原因而删除了一些重要的文件。当我们需要这些文件却找不到时&#xff0c;就会产生很大的困扰。那么&#xff0c;如果你的电脑中的文件被误删了&#xff0c;应该怎么找回被删除的文件呢?下面&#xff0c;小编整理出…

办公必备的高效翻译工具大揭秘

网易翻译是我最早接触的一款翻译工具&#xff0c;随着翻译时候需求的增加让开始了解其他的翻译工具。如果你也正在为你的翻译需求头疼那不妨看看我今天要介绍的工具有没有符合你需求的。 1.福昕在线翻译 链接直达&#xff1a;https://fanyi.pdf365.cn/doc 这个工具比较适合…

【大模型专栏—实战篇】基于RAG从0到1搭建AI科研知识库

大模型专栏介绍 &#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文为大模型专栏子篇&#xff0c;大模型专栏将持续更新&#xff0c;主要讲解大模型从入门到实战打怪升级。如有兴趣&#xff0c;欢迎您的阅读。 &#x1f4…

nvidia-docker Failed to initialize NVML: Unknown Error

nvidia镜像拉下来了&#xff0c;但是运行不了。 执行以下命令 sudo docker run --rm --runtimenvidia --gpus all ubuntu nvidia-smi报错 Failed to initialize NVML: Unknown Error参考 https://stackoverflow.com/questions/72932940/failed-to-initialize-nvml-unknown-er…