Qt 界面优化(绘图)

目录

  • 1. 绘图基本概念
  • 2. 绘制各种形状
    • 2.1 绘制线段
    • 2.2 绘制矩形
    • 2.3 绘制圆形
    • 2.4 绘制文本
    • 2.5 设置画笔
    • 2.6 设置画刷
  • 3. 绘制图片
    • 3.1 绘制简单图片
    • 3.2 平移图片
    • 3.3 缩放图片
    • 3.4 旋转图片
  • 4. 其他设置
    • 4.1 移动画家位置
    • 4.2 保存/加载画家的状态
  • 5. 特殊的绘图设备
    • 5.1 QPixmap
    • 5.2 QImage
    • 5.3 QPicture
  • 6. 其他话题

1. 绘图基本概念

(1)虽然 Qt 已经内置了很多的控件,但是不能保证现有控件就可以应对所有场景。

  • 很多时候我们需要更强的 “自定制” 能力。
  • Qt 提供了画图相关的 API,可以允许我们在窗口上绘制任意的图形形状,来完成更复杂的界面设计。

(2)所谓的 “控件”,本质上也是通过画图的方式画上去的。

  • 画图 API 和 控件 之间的关系,可以类比成机器指令和高级语言之间的关系。
  • 控件是对画图 API 的进⼀步封装;画图 API 是控件的底层实现。

(3)绘图 API 核心类。

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

(4)绘图 API 的使用一般不会在 QWidget 的构造函数中使用,而是要放到 paintEvent 事件中。关于 paintEvent:

  • paintEvent 会在以下情况下被触发:
    • 控件首次创建。
    • 控件被遮挡,再解除遮挡。
    • 窗口最小化,再恢复。
    • 窗口最小化,再恢复。
    • 控件大小发生变化时。
    • 主动调用 repaint() 或者 update() 方法。(这两个方法都是 QWidget 的方法)。
  • 因此,如果把绘图 api 放到构造函数中调用,那么⼀旦出现上述的情况,界面的绘制效果就无法确保符合预期了。

2. 绘制各种形状

2.1 绘制线段

(1)示例1:

void drawLine(const QPoint &p1, const QPoint &p2);
  • 参数:
    • p1:绘制起点坐标。
    • p2:绘制终点坐标。
  • 在 “widget.h” 头文件中声明绘图事件;

  • 在 “widget.cpp” 文件中重写 paintEvent() 方法;

  • 实现效果如下:

(2)示例2:

void drawLine ( int x1, int y1, int x2, int y2 );
  • 参数:
    • x1,y1:绘制起点坐标。
    • x2,y2:绘制终点坐标。

2.2 绘制矩形

(1)函数原型:

void QPainter::drawRect(int x, int y, int width, int height)
  • 参数:
    • x:窗口横坐标;
    • y:窗口纵坐标;
    • width:所绘制矩形的宽度;
    • height:所绘制矩形的高度;

(2)示例:

2.3 绘制圆形

(1)函数原型:

void QPainter::drawEllipse(const QPoint &center, int rx, int ry)
  • 参数:
    • center:中心点坐标;
    • rx:横坐标;
    • ry:纵坐标;

(2)示例:

  • 实现效果:

2.4 绘制文本

(1)QPainter类 中不仅提供了绘制图形的功能,还可以使用 QPainter::drawText() 函数来绘制文字,也可以使用QPainter::setFont() 设置字体等信息。示例:

  • 实现效果如下:

2.5 设置画笔

(1)QPainter 在绘制时,是有⼀个默认的画笔的。在使用时也可以自定义画笔。在 Qt 中,QPen类中定义了 QPainter 应该如何绘制形状、线条和轮廓。同时通过 QPen类 可以设置画笔的线宽、颜色、样式、画刷等。

  • 画笔的颜色可以在实例化画笔对象时进行设置,画笔的宽度是通过 setWidth() 方法进行设置,画笔的风格是通过setStyle()方法进行设置,设置画刷主要是通过 setBrush() 方法。
    • 设置画笔颜色:QPen::QPen(const QColor &color); 画笔的颜色主要是通过 QColor 类设置;
    • 设置画笔宽度:void QPen::setWidth(int width);
    • 设置画笔风格:void QPen::setStyle(Qt::PenStyle style);

(2)画笔的风格有:

(3)示例:画笔的使用。

  • 实现效果如下:

2.6 设置画刷

(1)在 Qt 中,画刷是使用 QBrush类 来描述,画刷大多用于填充。QBrush定义了QPainter的填充模式,具有样式、颜色、渐变以及纹理等属性。

  • 画刷的格式中定义了填充的样式,使用 Qt::BrushStyle 枚举,默认值是 Qt::NoBrush,也就是不进行任何填充。可以通过 Qt 助手查找画刷的格式。如下图示:
  • 设置画刷主要通过 void QPen::setBrush(const QBrush &brush) 方法,其参数为画刷的格式。

(2)示例:

  • 实现效果:

3. 绘制图片

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

  • 其中QImage主要用来进行 I/O 处理,它对 I/O 处理操作进行了优化,而且可以用来直接访问和操作像素;QPixmap 主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;QBitmap 是 QPixmap 的子类,用来处理颜色深度为1的图像,即只能显示黑白两种颜色;QPicture 用来记录并重演 QPainter 命令。这⼀节只讲解 QPixmap。

3.1 绘制简单图片

(1)新建 Qt 项目,基类选择 QWidget,项目名称为 QPainter。在 “widget.h” 头文件中声明绘画事件;如下图示:

  • 添加资源文件;首先准备⼀些图片资源文件,并将这些图片资源文件放在同⼀个文件夹中,将该文件夹复制到本项目中。

  • 选中项目文件,鼠标右键 -------> add new… 。

  • 点击 “add new…” 之后,出现如下界面:

  • 选择 “Choose…” 之后,给资源文件命名;

  • 点击 “下⼀步”,出现如下界面,点击 “完成”;

  • 给资源文件添加前缀,并将资源文件添加至项目中;

  • 将所有的资源文件添加到项目中,方便后续使用;

  • 点击 “构建并运行” 按钮,将资源文件添加到项目中;

  • 在 “widget.cpp” 文件中实现画图片功能;

  • 实现效果如下:

3.2 平移图片

(1)平移图片实际是通过改变坐标来实现。QPainter类中提供了 translate()函数 来实现坐标原点的改变。如下示例:

  • 实现效果如下:

3.3 缩放图片

(1)在 Qt 中,图片的放大和缩小可以使用 QPainter类 中的 drawPixmap()函数 来实现。示例:

  • 实现效果如下:

3.4 旋转图片

(1)图片的旋转使用的是 QPainter类 中的 rotate()函数,它默认是以原点为中心进行旋转的。如果要改变旋转的中心,可以使用 translate()函数 完成。示例:

  • 实现效果如下:

4. 其他设置

4.1 移动画家位置

(1)有时候在绘制多个图形时,想使用同一坐标位置,那么绘制出来的图形肯定会重合,此时,可以通过移动画家的位置来使图形不发生重合。

  • 示例1:未移动画家位置。

  • 实现效果如下:

  • 示例2:移动画家位置。使用 translate 移动画家所在位置:

  • 实现效果如下:

4.2 保存/加载画家的状态

(1)在绘制图形的过程中,可以通过 save() 函数来保存画家的状态,使用 restore() 函数还原画家状态。

  • save() 函数原型如下:
void QPainter::save();

  • restore() 函数原型如下:
void QPainter::restore();

(2)示例:

  • 实现效果如下:

(3)说明:

  • 上述示例中,在画第三个圆之前,由于还原了画家的状态,所以此时画家的位置坐标会移动到画家状态保存的地方,所以在绘制第三个圆的位置时实际是和第⼆个圆发生了重叠。

5. 特殊的绘图设备

(1)前面的代码中我们是使用 QWidget 作为绘图设备。在 Qt 中还存在下列三个比较特殊的绘图设备。此处我们也简要介绍。

  • QPixmap 用于在显示器上显示图片。
  • QImage 用于对图片进行像素级修改。
  • QPicture 用于对 QPainter 的⼀系列操作进行存档。

5.1 QPixmap

(1)QPixmap 核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。
  • 通过文件路径加载并显示图片。
  • 搭配 QPainter 的 drawPixmap()函数,可以把这个图片绘制到⼀个 QLabel、QPushButton 等控件上。
  • 和系统/显示设备强相关,不同系统/显示设备下,QPixmap 的显示可能会有所差别。

(2)示例:

  • 实现效果:


5.2 QImage

(1)QImage 的核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。
  • 通过文件路径加载并显示图片。
  • 能够针对图片进行像素级别的操作(操作某个指定的像素)。
  • 独立于硬件的绘制系统,能够在不同系统之上提供⼀致的显示。

(2)代码示例:QImage 作为绘图设备的使用。

(3)代码示例:QImage 绘图时对像素的修改。

  • 新建 Qt 项目,添加图片资源文件到项目中;如下图示:
  • 在 widget.h 头文件中声明绘图事件;

  • 在 widget.cpp 文件中重写绘图事件,使用 QImage 对图片像素进行修改;
    • 通过 setPixel 设置某个像素的颜色值。
    • 使用 qRgb 表示⼀个具体的颜色。

  • 执行效果如下:
    • 没有修改像素之前:

  • 修改像素之后:

5.3 QPicture

(1)QPicture 核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。
  • 通过文件路径加载并显示图片。
  • 能够记录 QPainter 的操作步骤。
  • 独立于硬件的绘制系统,能够在不同系统之上提供⼀致的显示。

(2)注意:
QPicture 加载的必须是自身的存档文件,而不能是任意的 png, jpg 等图片文件。

(3)QPicture 类似于很多游戏的 Replay 功能。

  • 例如像 war3 这样的经典游戏,即使是⼀场 60 分钟的膀胱局,生成的 replay 文件,也不过几百个 KB。
  • 此处的 Replay 功能并非是把整个游戏画面都录制保存下来,而是记录了地图中发生的所有事件(地图元素,玩家单位操作,中立生物行为等…)。
  • 当回放 Replay 的时候其实就是把上述记录的事件再⼀条⼀条的执行⼀遍即可还原之前的游戏场景了。
  • 不了解游戏的也可以理解成警察录笔录,并通过笔录还原案发现场。

(4)如果要记录下 QPainter 的命令,首先要使用 QPainter::begin() 函数,将 QPicture 实例作为参数传递进去,以便告诉系统开始记录,记录完毕后使用 QPainter::end() 命令终至。如下示例:

  • 实现效果:

  • 通过 QPicture 重现绘图指令后,实现的效果如下:

6. 其他话题

(1)Qt 中对于界面的优化美化,还涉及到很多其他的话题。

  • Qt 动画 。
  • Qt 3D 图形 。
  • QQuick 。
  • 使用第三方控件库。
  • Qt Design Studio 。

(2)Qt 的QSS介绍见博客:https://blog.csdn.net/m0_65558082/article/details/147787398?spm=1001.2014.3001.5502

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

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

相关文章

【计算机视觉】优化MVSNet可微分代价体以提高深度估计精度的关键技术

优化MVSNet可微分代价体以提高深度估计精度的关键技术 1. 代价体基础理论与分析1.1 标准代价体构建1.2 关键问题诊断 2. 特征表示优化2.1 多尺度特征融合2.2 注意力增强匹配 3. 代价体构建优化3.1 自适应深度假设采样3.2 可微分聚合操作改进 4. 正则化与优化策略4.1 多尺度代价…

Python中,async和with结合使用,有什么好处?

在Python的异步编程中,async和with的结合使用(即async with)为开发者提供了一种优雅且高效的资源管理模式。这种组合不仅简化了异步代码的编写,还显著提升了程序的健壮性和可维护性。以下是其核心优势及典型应用场景的分析&#x…

【金仓数据库征文】金仓数据库:创新驱动,引领数据库行业新未来

一、引言 在数字化转型的时代洪流中,数据已跃升为企业的核心资产,宛如企业运营与发展的 “数字命脉”。从企业日常运营的精细化管理,到战略决策的高瞻远瞩制定;从客户关系管理的深度耕耘,到供应链优化的全面协同&…

Python学习之路(玖)-图像识别的实现

在 Python 中,图像识别对比通常涉及 图像相似度计算 或 目标检测与匹配。-浅看一下就行,具体功能代码,后期会逐步上传资源。 一、技术方案 1. 图像相似度计算 目标:计算两幅图像的相似度。工具: OpenCV:图…

【C语言文件操作详解】fopen 函数全解析 —— 模式参数、使用技巧与重定向的区别

在 C 语言中,文件的读写是一个非常常见的需求。fopen 是标准库中提供的函数,用来打开文件,返回一个文件指针供后续操作使用。本篇博客将详细介绍 fopen 的使用方法、每个参数的含义,以及它与 Shell 中 >、>> 重定向符的联…

青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程

青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程 一、游戏规则二、实现步骤1. 创建项目2. 编写代码3. 添加依赖4. 运行程序 三、代码解析四、println! 的用法基本用法使用占位符示例控制输出宽度和精度示例 输出多个变量示例 注意事项小结 五、管理多个项目1. 创建 Wo…

拒绝flash插件打劫!如何在vscode上玩4399小游戏

现在电脑上玩4399都需要flash插件了 这也导致了很多人无法玩到小时候的游戏 今天介绍一款插件 功能强大 即安即玩 首先打开vscode 点开小方框(拓展)搜索4399 认准4399 on vscode点击安装 安装完毕后 按下 Ctrl Shift P , 输入 4399 on VSCode 或…

RHCSA Linux系统 Web页面 论坛 网盘的搭建

Web 服务搭建 [rootlocalhost ~]#yum install httpd -y [rootlocalhost ~]#cd /var/www/htm1/ [rootalocalhost html]#echo 江停严峫 >index.html [rootlocalhost html]#setenforce 0 #将 SELinux 模式设置为宽容模式,不强制执行安全策略 [rootlocalhost h…

力扣刷题——二分查找总结

我们可以总结出二分查找的通用做法和常见变种。二分查找是一种在有序数组中高效查找元素的算法,时间复杂度为 O (log n)。 二分查找的通用模板 二分查找的核心思想是将搜索范围不断缩小一半,直到找到目标元素或确定其不存在。以下是通用模板&#xff1…

开源数字人框架 AWESOME-DIGITAL-HUMAN 技术解析与应用指南

一、项目概述 AWESOME-DIGITAL-HUMAN 是一个基于 Live2D 技术的开源数字人框架,它集成了语音识别(ASR)、大语言模型(LLM)、语音合成(TTS)和 Agent 模块化扩展能力,支持快速部署和自…

互联网大厂Java求职面试:基于RAG的智能问答系统设计与实现-2

互联网大厂Java求职面试:基于RAG的智能问答系统设计与实现-2 面试背景 郑薪苦是一名Java开发者,拥有丰富的项目经验,但在面试中总喜欢用奇葩比喻解释技术问题。今天他面对的是某大厂技术总监张总,面试主题为“基于RAG的智能问答…

(二)Linux下基本指令 2

【知识预告】 16. date 指令 17. cal 指令 18. find 指令 19. which指令 20. whereis 指令 21. alias 指令 22. grep 指令 23. zip/unzip 指令 24. tar 指令 25. bc 指令 26. uname ‒r 指令 27. 重要的⼏个热键 28. 关机 16 date 指令 指定格式显⽰时间:date %Y-…

命令行解释器中shell、bash和zsh的区别

命令行解释器(Command Line Interpreter)是一个程序,它的主要作用是接收用户输入的命令,并执行相应的操作。它充当了用户与操作系统内核之间的桥梁。 一、什么是 Shell? Shell 是一个通用术语,指的是 命令…

二、transformers基础组件之Tokenizer

在使用神经网络处理自然语言处理任务时,我们首先需要对数据进行预处理,将数据从字符串转换为神经网络可以接受的格式,一般会分为如下几步: - Step1 分词:使用分词器对文本数据进行分词(字、字词);- Step2 构建词典:根据数据集分词的结果,构建…

镜像和容器的管理

一、镜像的管理 获取镜像并生成相关容器 # 拉取镜像 docker pull alpine # 默认是latest,也就是最新版本,也可指定版本(在镜像名后边加“:版本号”) # 或者 # 从主机中导入镜像到docker中 docker image load -i /test#生成容器 …

设计模式简述(十九)桥梁模式

桥梁模式 描述基本组件使用 描述 桥梁模式是一种相对简单的模式,通常以组合替代继承的方式实现。 从设计原则来讲,可以说是单一职责的一种体现。 将原本在一个类中的功能,按更细的粒度拆分到不同的类中,然后各自独立发展。 基本…

ImportError: DLL load failed: 找不到指定的程序。

查看其他博客说是缺少libssl-1_1-x64.dll 和 libcrypto-1_1-x64.dll 然后去下载放到博客说的目录下 没有用 解决不了一点 OpenSSL for Windows 64位 完整安装包 在这里 项目地址: https://gitcode.com/open-source-toolkit/eb627 注意事项 此安装包仅适用于64位Windows系…

电池单元和电极性能

电芯设计中的挑战 对于电池制造商来说,提高电池能量和功率密度至关重要。在高功率密度和长循环寿命之间取得平衡是电池设计中的关键挑战,通常需要仔细优化材料、电极结构和热管理系统。另一个关键挑战是通过优化重量体积比来降低电池单元的总体成本。 工…

数据加密与隐私保护:让你的信息固若金汤

数据加密与隐私保护:让你的信息固若金汤 大家好,我是 Echo_Wish,今天聊聊一个 人人都关心、但很多人没做好 的话题——数据加密与隐私保护的最佳实践。 为什么要重视数据安全? 现在是数字化时代,从个人照片、银行卡信息到企业机密,数据泄露的风险无处不在。你可能觉得自…

【高数上册笔记篇02】:数列与函数极限

【参考资料】 同济大学《高等数学》教材樊顺厚老师B站《高等数学精讲》系列课程 (注:本笔记为个人数学复习资料,旨在通过系统化整理替代厚重教材,便于随时查阅与巩固知识要点) 仅用于个人数学复习,因为课…