Qt——界面优化

news/2025/1/20 21:32:28/

一.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文档获取。 



http://www.ppmy.cn/news/1564758.html

相关文章

React进阶之react.js、jsx模板语法及babel编译

React React介绍React官网初识React学习MVCMVVM JSX外部的元素props和内部的状态statepropsstate 生命周期constructorgetDerivedStateFromPropsrendercomponentDidMount()shouldComponentUpdategetSnapshotBeforeUpdate(prevProps, prevState) 创建项目CRA:create-…

【Rust自学】13.8. 迭代器 Pt.4:创建自定义迭代器

13.8.0. 写在正文之前 Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。 在本章中,我们会讨论 Rust 的一…

多租户支持与企业级应用场景:ShardingSphere 的应用解析

随着企业业务的多样化和复杂性增加,多租户架构成为支持多个独立用户或租户在同一系统上高效、安全地运行的关键方案。ShardingSphere 提供了强大的多租户支持,使得在分布式数据库环境下,多个租户可以共享资源,同时保证数据隔离与安…

服务化架构 IM 系统之应用 MQ

在微服务化系统中,存在三个最核心的组件,分别是 RPC、注册中心和MQ。 在前面的两篇文章(见《服务化架构 IM 系统之应用 RPC》和《服务化架构 IM 系统之应用注册中心》)中,我们站在应用的视角分析了普适性的 RPC 和 注…

RV1126+FFMPEG推流项目(5)VI和VENC模块绑定,并且开启线程采集

回顾一下这个图,前面VI和VENC已经初始化了,现在也已经到了绑定两个模块的时候了。最后才开启线程到通道里面拿数据。 接下要完成这个两个模块, rkmedia_assignment_manage.cpp (任务管理模块),管理 RV1126 上的各个任务。主要任…

Comment(爆破+git泄漏+二次注入)

通过爆破密码的后三位,获得账号为:zhangwei666 F12查看控制台 使用bugscanteam的githack工具,下载泄漏的源码,根据控制台的提示,完整源码还在历史的commit中 git log –reflog 查看历史记录 查看最新的提交记录&#…

@Scope(“prototype“)

Scope("prototype") 是 Spring 框架中用于定义 Bean 作用域的注解之一,它的主要作用是将一个 Bean 定义成 原型作用域(Prototype Scope)。在原型作用域下,每次从 Spring 容器中请求这个 Bean 时,都会创建一个…

Windows蓝牙驱动开发-蓝牙 IOCTL

蓝牙驱动程序堆栈为配置文件驱动程序提供了多个 IOCTL,来收集有关以下内容的信息: 本地蓝牙无线电和系统; 远程蓝牙设备; 会使即插即用 (PnP) 管理器加载配置文件驱动程序的设备; 为收集有关本地蓝牙无线电和系统的…