如何在Qt中绘制一个带有动画的弧形进度条?
如何在Qt中绘制一个弧形的进度条
在图形用户界面开发中,进度指示控件(Progress Widget)是非常常见且实用的组件。CCArcProgressWidget
是一个继承自 QWidget
的自定义控件,用于绘制圆弧形进度条。当然,笔者看了眼公开的实现,基本上都非常完善了,笔者在这里添加了一个更好的动画。
类定义概览
CCArcProgressWidget
类定义在 CCArcProgressWidget.h
中,使用 Qt 元对象系统,通过 Q_OBJECT
宏启用信号与属性机制。该控件支持如下属性绑定:
value
:当前进度值maxValue
:最大进度值displayValue
:动画过程中的显示值(与实际value
异步)
这些属性可被 QML 或动画机制绑定,便于动态效果的呈现。(笔者这里使用的是Q_PROPERTY属性系统公开的,所以QML可用(笑))
静态常量定义(这部分是笔者认为编译的时候可以指定的)
类中定义了多个静态常量,用于控制组件的外观与行为:
DURATION
:动画持续时间(单位:毫秒),默认为 500msARC_WIDTH
:圆弧的线宽,默认为 50 像素DEFAULT_VALUE
:默认初始值,为 0DEFAULT_MAX
:默认最大值,为 100DEF_TEXT_COLOR
:默认文本颜色DEF_BKCOLOR
:默认背景弧颜色(未完成部分)DEF_ARC_COLOR
:默认进度弧颜色(已完成部分)
这些常量使得控件具有清晰的默认状态,便于使用和维护。
属性访问与设置接口
该类提供了一系列 inline
内联函数和公开接口,用于读取与设置进度值及外观样式:
int value() const
:获取当前进度值void setValue(int val)
:设置当前进度值(含动画)int maxValue() const
:获取最大值void setMaxValue(int max)
:设置最大值QColor progressArcColor() const
/void setProgressArcColor(const QColor&)
:读取与设置进度弧颜色QColor progressBackgroundColor() const
/void setProgressBackgroundColor(const QColor&)
:读取与设置背景弧颜色QColor progressTextColor() const
/void setProgressTextColor(const QColor&)
:读取与设置文本颜色
所有设置函数内部均会判断是否真正发生变化,避免无谓的刷新,若发生更改则调用 update()
触发重绘。
信号机制
该控件定义了三个信号:
valueChanged(int)
:当用户设置新进度值时发出maxValueChanged(int)
:当最大值被重新设置时发出displayValueChanged(int)
:当动画中显示的值发生变化时发出
这些信号便于其他模块(如界面展示、数据记录)实时响应进度的变化。
绘制函数与动画支持
该类重载了 paintEvent
事件处理函数,实现核心绘制逻辑。绘制内容包括三部分:
- 背景弧:通过
drawBackgroundArc()
绘制未完成部分 - 进度弧:通过
drawProgressArc()
根据当前动画角度绘制完成部分 - 中心文本:通过
drawText()
绘制当前数值或状态文字
同时,setupAnimation()
函数用于构建 QPropertyAnimation
动画,使 value
到 displayValue
之间具备平滑过渡效果。动画期间实际值不变,仅 displayValue
动态变化,从而提升用户体验。
私有成员变量
类中使用了如下私有成员保存状态:
progress_value
:当前进度值progress_display_value
:当前显示值(用于动画)progress_max_value
:最大进度值progress_minAngle
与progress_startAngle
:控制弧线的起始与方向(默认从顶部顺时针)progress_arc_color
、progress_backgroundColor
、progress_textColor
:颜色配置QPropertyAnimation* animation
:动画对象指针
这些成员变量共同构成了进度显示的完整状态。
使用示例(简要)
CCArcProgressWidget* widget = new CCArcProgressWidget(this);
widget->setValue(70);
widget->setMaxValue(100);
widget->setProgressArcColor(Qt::blue);
widget->setProgressBackgroundColor(Qt::lightGray);
widget->setProgressTextColor(Qt::black);
以上代码将在界面中创建一个蓝色的圆形进度条,表示当前进度为 70%。
一些实现的细节说明
下面的部分是属性设置的接口,没什么有趣的。
#include "CCArcProgressWidget.h"
#include <QPropertyAnimation>CCArcProgressWidget::CCArcProgressWidget(QWidget* parent): QWidget { parent } {setupAnimation();
}void CCArcProgressWidget::setupAnimation() {animation = new QPropertyAnimation(this, "displayValue");animation->setDuration(DURATION);animation->setEasingCurve(QEasingCurve::OutCubic);
}void CCArcProgressWidget::setValue(int val) {val = qBound(0, val, progress_max_value);if (val == progress_value) // avoid duplicate animationsreturn;progress_value = val;animation->stop();animation->setStartValue(progress_display_value);animation->setEndValue(progress_value);animation->start();
}
下面说下我们的绘制,这里是每一次触发重绘的时候我们的设备实际上进行的绘制。
void CCArcProgressWidget::paintEvent(QPaintEvent* event [[maybe_unused]]) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);QRectF baseRect = rect();double side = qMin(baseRect.width(), baseRect.height());// 到这里,是为了获取绘制成正方形而不是椭圆形(不然太难看了)QRectF squareRect((baseRect.width() - side) / 2.0,(baseRect.height() - side) / 2.0,side, side);int margin = ARC_WIDTH + 5;QRectF arcRect = squareRect.adjusted(margin, margin, -margin, -margin);double radius = qMin(arcRect.width(), arcRect.height()) / 2;QPointF center = arcRect.center();double angle = 360.0 * progress_display_value / progress_max_value;angle = qMax<double>(progress_minAngle, -angle);drawBackgroundArc(painter, arcRect);drawProgressArc(painter, arcRect, angle);drawText(painter, center, radius);
}
paintEvent
事件首先确定绘制区域arcRect
,再根据当前displayValue
计算对应的角度angle
。之后,依次调用:
drawBackgroundArc
:用圆弧绘制背景轨迹。drawProgressArc
:绘制当前进度的圆弧,同时在圆弧末端绘制小圆点,增强视觉效果。drawText
:居中绘制当前进度的百分比文本。
void CCArcProgressWidget::drawBackgroundArc(QPainter& painter, const QRectF& arcRect) {QPen pen(progress_backgroundColor, ARC_WIDTH);pen.setCapStyle(Qt::RoundCap);painter.setPen(pen);painter.drawArc(arcRect, progress_startAngle * 16, 360 * 16);
}void CCArcProgressWidget::drawProgressArc(QPainter& painter, const QRectF& arcRect, double angle) {if (angle == 0)return;QConicalGradient gradient(arcRect.center(), progress_startAngle);gradient.setColorAt(0, progress_arc_color.lighter(150));gradient.setColorAt(0.5, progress_arc_color);gradient.setColorAt(1, progress_arc_color.darker(150));QPen pen(QBrush(gradient), ARC_WIDTH);pen.setCapStyle(Qt::FlatCap);painter.setPen(pen);painter.drawArc(arcRect, progress_startAngle * 16, -angle * 16);double spanAngleRad = qDegreesToRadians(progress_startAngle - angle);double cx = arcRect.center().x();double cy = arcRect.center().y();double rx = arcRect.width() / 2;double ry = arcRect.height() / 2;double ex = cx + rx * qCos(spanAngleRad);double ey = cy - ry * qSin(spanAngleRad);QBrush brush(gradient);painter.setBrush(brush);painter.setPen(Qt::NoPen);painter.drawEllipse(QPointF(ex, ey), ARC_WIDTH / 2.0, ARC_WIDTH / 2.0);
}void CCArcProgressWidget::drawText(QPainter& painter, const QPointF& center, double radius) {painter.setFont(QFont("Arial", radius * 0.3, QFont::Bold));painter.setPen(progress_textColor);QString text = QString("%1%").arg(qRound(100.0 * progress_display_value / progress_max_value));QRectF textRect(center.x() - radius, center.y() - radius,radius * 2, radius * 2);painter.drawText(textRect, Qt::AlignCenter, text);
}
相关文章:

如何在Qt中绘制一个带有动画的弧形进度条?
如何在Qt中绘制一个弧形的进度条 在图形用户界面开发中,进度指示控件(Progress Widget)是非常常见且实用的组件。CCArcProgressWidget 是一个继承自 QWidget 的自定义控件,用于绘制圆弧形进度条。当然,笔者看了眼公开…...
参加技术会议,为程序人生的职业生涯成长添砖加瓦
参加技术会议,为程序人生的职业生涯成长添砖加瓦 关键词:技术会议、程序员职业生涯、职业成长、技术交流、人脉拓展、知识体系升级、职业竞争力 摘要:在快速迭代的IT技术领域,参加技术会议已成为程序员突破职业瓶颈、构建核心竞争力的重要途径。本文从技术会议的核心价值出…...

国产三维CAD皇冠CAD(CrownCAD)建模教程:汽车电池
在线解读『汽车电池』的三维建模流程,讲解3D草图、保存实体、拉伸凸台/基体、设置外观等操作技巧,一起和皇冠CAD(CrownCAD)学习制作步骤吧! 汽车电池(通常指铅酸蓄电池或锂离子电池)是车辆电气系…...
记录算法笔记(2025.5.28)只出现一次的数字
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 示例 1 : 输入࿱…...

VMware-workstation安装教程--超详细(附带安装包)附带安装CentOS系统教程
VMware-workstation安装教程--超详细(附带安装包)附带安装CentOS系统教程 一、下载软件VMwware二、下载需要的镜像三、在VMware上安装系统 一、下载软件VMwware 二、下载需要的镜像 三、在VMware上安装系统 VMware 被 Broadcom(博通&#x…...

2025年- H63-Lc171--33.搜索旋转排序数组(2次二分查找,需二刷)--Java版
1.题目描述 2.思路 输入:旋转后的数组 nums,和一个整数 target 输出:target 在 nums 中的下标,如果不存在,返回 -1 限制:时间复杂度为 O(log n),所以不能用遍历,必须使用 二分查找…...

3D-激光SLAM笔记
目录 定位方案 编译tbb ros2humble安装 命令 colcon commond not found 栅格地图生成: evo画轨迹曲线 安装gtsam4.0.2 安装ceres-solver1.14.0 定位方案 1 方案一:改动最多 fasterlio 建图,加闭环优化,参考fast-lio增加关…...
Golang 配置国内代理
使用 GOPROXY 临时设置 export GOPROXYhttps://goproxy.cn,direct永久设置 go env -w GOPROXYhttps://goproxy.cn,direct再go get下载...
Android bindservice绑定服务,并同步返回service对象的两个方法
先上一段代码: private IDeviceService deviceService null; private ServiceConnection connnull; private synchronized void bindyourservice() { Intent intent new Intent();intent.setPackage("servicepackagename");intent.setAction("…...
5G 核心网 UE 状态深度剖析:机制、迁移与演进
摘要 本文围绕 5G 核心网中 UE(用户设备)状态展开系统分析,详细阐述了 UE 状态的定义、分类及特点,深入探讨各状态间的迁移流程与关键技术,并结合典型应用场景分析其实际价值。同时,对比 4G 技术剖析 5G 的改进之处,展望 6G 时代 UE 状态管理的演进方向,为 5G 网络优化…...

HomeKit 基本理解
概括 HomeKit 将用户的家庭自动化信息存储在数据库中,该数据库由苹果的内置iOS家庭应用程序、支持HomeKit的应用程序和其他开发人员的应用程序共享。所有这些应用程序都使用HomeKit框架作为对等程序访问数据库. Home 只是相当于 HomeKit 的表现层,其他应用在实现 …...
[SC]SystemC在CPU/GPU验证中的应用(三)
SystemC在CPU/GPU验证中的应用(三) 摘要:下面分享50个逐步升级SystemC编程能力的示例及建议的学习路线图。您可以一次一批地完成它们——从前五个基础的例子开始,然后转向channels, TLM, bus models, simple CPU/GPU kernels等等。在每个阶段掌握之后,再进行下一组…...
gunicorn多线程部署django导致的登陆错误
使用django写后端,认证系统使用了内存中的令牌存储(authentication.py中的user_tokens字典)。 from secrets import token_hex from .models import User# Create a custom token generation function def generate_token():return token_he…...

(LeetCode 每日一题) 909. 蛇梯棋 (广度优先搜索bfs)
题目:909. 蛇梯棋 思路:广度优先搜索bfs队列,时间复杂度0(6*n^2)。 细节看注释 C版本: class Solution { public:int snakesAndLadders(vector<vector<int>>& board) {int nboard.size();// vis[i]:…...
PostgreSQL ERROR: out of shared memory处理
使用pg_dump命令导出一个库的时候,报 pg_dump: error: query failed: ERROR: out of shared memory HINT: You might need to increase "max_locks_per_transaction". 从错误字面上看是超出内存大小了,建议增加max_locks_per_transaction参…...

生成https 证书步骤
一、OpenSSL下载 OpenSSL下载地址: https://slproweb.com/products/Win32OpenSSL.html 如果电脑是64位的就选择64位的 二、OpenSSL安装 双击打开.exe文件 开始安装,一直下一步,不过需要注意的是默认安装路径是C盘,可更改到其他盘…...
34、请求处理-【源码分析】-Model、Map原理
34、请求处理-【源码分析】-Model、Map原理 在 Spring Boot 中,处理请求时,控制器方法可以接收 Model 和 Map 类型的参数,用于向视图传递数据。以下是 Model 和 Map 参数处理的原理分析: ### 1. 参数解析过程 #### **1.1 确定参数…...

设计模式——适配器设计模式(结构型)
摘要 本文详细介绍了适配器设计模式,包括其定义、核心思想、角色、结构、实现方式、适用场景及实战示例。适配器模式是一种结构型设计模式,通过将一个类的接口转换成客户端期望的另一个接口,解决接口不兼容问题,提高系统灵活性和…...

小黑大语言模型通过设计demo进行应用探索:langchain中chain的简单理解demo
chain简介 LangChain 中的 Chain 模块在开发大型语言模型(LLM)驱动的应用程序中起着至关重要的作用。Chain是串联LLM能力与实际业务的关键桥梁,通过将多个工具和模块按逻辑串联起来,实现复杂任务的多步骤流程编排。 案例 通过…...

秒杀系统—5.第二版升级优化的技术文档三
大纲 8.秒杀系统的秒杀库存服务实现 9.秒杀系统的秒杀抢购服务实现 10.秒杀系统的秒杀下单服务实现 11.秒杀系统的页面渲染服务实现 12.秒杀系统的页面发布服务实现 8.秒杀系统的秒杀库存服务实现 (1)秒杀商品的库存在Redis中的结构 (2)库存分片并同步到Redis的实现 (3…...
[SC]SystemC在CPU/GPU验证中的应用(六)
SystemC在CPU/GPU验证中的应用(六) 摘要:下面分享50个逐步升级SystemC编程能力的示例及建议的学习路线图。您可以一次一批地完成它们——从前五个基础的例子开始,然后转向channels, TLM, bus models, simple CPU/GPU kernels等等。在每个阶段掌握之后,再进行下一组…...

【STM32】HAL库 之 CAN 开发指南
基于stm32 f407vet6芯片 使用hal库开发 can 简单讲解一下can的基础使用 CubeMX配置 这里打开CAN1 并且设置好波特率和NVIC相关的配置 波特率使用波特率计算器软件 使用采样率最高的这段 填入 得到波特率1M bit/s 然后编写代码 环形缓冲区 #include "driver_buffer.h&qu…...
WPF的基础设施:XAML基础语法
XAML基础语法 1 控件声明与属性设置1.1 特性语法(Attribute Syntax)1.2 属性元素语法(Property Element Syntax)1.3 特殊值标记扩展 2 x:Name与Name的区别3 注释与代码折叠4 实用技巧集合5 常见错误排查 XAML( Extensible Applic…...

DeepSeek R1-0528 新开源推理模型(免费且快速)
DeepSeek推出了新模型,但这不是R2! R1-0528是DeepSeek的最新模型,在发布仅数小时后就在开源社区获得了巨大关注。 这个悄然发布的模型DeepSeek R1-0528,已经开始与OpenAI的o3一较高下。 让我来详细介绍这次更新的新内容。 DeepSeek R1-0528 发布 DeepSeek在这次发布中采…...

Go 语言的 GC 垃圾回收
序言 垃圾回收(Garbage Collection,简称 GC)机制 是一种自动内存管理技术,主要用于在程序运行时自动识别并释放不再使用的内存空间,防止内存泄漏和不必要的资源浪费。这篇文章让我们来看一下 Go 语言的垃圾回收机制是如…...
[git每日一句]your branch is behind ‘origin/master‘
当 Git 提示 "your branch is behind origin/master" 时,意思是: 你的本地分支落后于远程仓库(origin)的 master 分支 即:远程仓库有新的提交,而你的本地分支尚未同步这些更新。 如何解决&…...
【QT】在QT6中读取文件的方法
在QT6中读取文件的方法 QT6提供了多种读取文件的方式,下面我将介绍几种常用的方法,包括处理文本文件和二进制文件。 1. 使用QFile和QTextStream读取文本文件 这是读取文本文件最常用的方法: #include <QFile> #include <QTextSt…...

安全帽目标检测
安全帽数据集 这里我们使用的安全帽数据集是HelmentDetection,这是一个公开数据集,里面包含5000张voc标注格式的图像,分为三个类别,分别是 0: head 1: helmet 2: person 安全帽数据集下载地址、 我们将数据集下载后,…...
Java工厂方法模式详解
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它将对象的创建和使用分离,通过定义一个创建对象的接口,让子类决定实例化哪个类。这种模式提高了代码的可扩展性和可维护性,尤其适用于需要根据…...
【pytorch学习】土堆pytorch学习笔记2
说明 主要以https://www.morinha.cc/posts/courses/pytorch-%E5%B0%8F%E5%9C%9F%E5%A0%86的内容为基础,没有的或者自己不是很清楚的再补充上内容,该贴有的内容大部分不再加入进来 新增的更全的参考: https://2048.csdn.net/6801fc28e9858151…...