Qt 实现波浪填充的圆形进度显示

devtools/2025/3/16 21:13:19/

话不多说,先上效果图

代码示例:

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPropertyAnimation>
#include <QTimer>
#include <cmath>class WaveProgressBar : public QWidget
{Q_OBJECTQ_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)Q_PROPERTY(qreal wavePhase READ wavePhase WRITE setWavePhase)
public:explicit WaveProgressBar(QWidget *parent = nullptr): QWidget(parent), m_min(0), m_max(100), m_value(0),m_wavePhase(0), m_waveAmplitude(10), m_waveLength(150),m_waveColor(QColor(100, 180, 255)){//设置无边框和背景透明//setWindowFlags(windowFlags() |  Qt::FramelessWindowHint | Qt::Tool);//setAttribute(Qt::WA_TranslucentBackground);// 波浪相位动画QPropertyAnimation *waveAnim = new QPropertyAnimation(this, "wavePhase");waveAnim->setDuration(1000);waveAnim->setStartValue(0);waveAnim->setEndValue(m_waveLength);waveAnim->setLoopCount(-1);waveAnim->start();setMinimumSize(150, 150);resize(150, 150);}int value() const { return m_value; }qreal wavePhase() const { return m_wavePhase; }void setValue(int value){value = qBound(m_min, value, m_max);if (m_value != value) {m_value = value;update();emit valueChanged(m_value);}}void setWavePhase(qreal phase){m_wavePhase = phase;update();}void setWaveColor(const QColor &color){m_waveColor = color;update();}void setWaveAmplitude(const qreal amplitude){m_waveAmplitude = amplitude;}signals:void valueChanged(int value);protected:void paintEvent(QPaintEvent *) override{QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);const qreal side = qMin(width(), height());const QRectF rect(0, 0, side, side);const QPointF center = rect.center();const qreal radius = side / 2.0;// 计算填充进度const qreal progress = (m_value - m_min) / static_cast<qreal>(m_max - m_min);const qreal fillHeight = rect.height() * (1 - progress);// 创建统一背景(使用波浪颜色的深色版本)painter.setPen(Qt::NoPen);painter.setBrush(m_waveColor.darker(150));painter.drawEllipse(center, radius, radius);// 创建波浪路径(始终覆盖整个圆形)QPainterPath wavePath;const qreal waterLevel = fillHeight;const qreal baseY = rect.top() + waterLevel;wavePath.moveTo(rect.left() - m_waveLength, baseY);// 生成波浪曲线for (qreal x = rect.left() - m_waveLength; x < rect.right() + m_waveLength; x += 1.0) {const qreal phase = (x + m_wavePhase) * M_PI / (m_waveLength / 2.0);const qreal y = baseY + m_waveAmplitude * sin(phase);wavePath.lineTo(x, y);}// 闭合路径形成填充区域wavePath.lineTo(rect.bottomRight() + QPointF(m_waveLength, 0));wavePath.lineTo(rect.bottomLeft() - QPointF(m_waveLength, 0));wavePath.closeSubpath();// 创建圆形裁剪路径,控制波浪在圆形区域内QPainterPath clipPath;clipPath.addEllipse(center, radius, radius);painter.setClipPath(clipPath);// 绘制渐变波浪QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());gradient.setColorAt(0, m_waveColor.lighter(120));gradient.setColorAt(1, m_waveColor.darker(120));painter.setBrush(gradient);painter.drawPath(wavePath);// 绘制中心文本painter.setPen(Qt::white);painter.setFont(QFont("Arial", radius * 0.35, QFont::Bold));painter.drawText(rect, Qt::AlignCenter, QString::number(progress * 100, 'f', 0) + "%");}private:int m_min;int m_max;int m_value;qreal m_wavePhase;qreal m_waveAmplitude; //波浪振幅qreal m_waveLength;    //波浪长度QColor m_waveColor;
};int main(int argc, char *argv[])
{QApplication a(argc, argv);static int value = 0;WaveProgressBar progressBar;progressBar.show();QTimer timer;QObject::connect(&timer, &QTimer::timeout, &progressBar, [&progressBar](){ progressBar.setValue(++value);  });timer.start(1000);return a.exec();
}#include "main.moc"

具体实现效果可自由调整,
m_waveColor代表波浪颜色,示例代码改变m_waveColor亮度绘制背景,可自由修改。
水波效果由波长和振幅控制 “大振幅+长波长=平缓波浪”, “小振幅+短波长=密集波纹”。

通过 waveAnim->setDuration(1000);设置动画周期可改变水波速度


http://www.ppmy.cn/devtools/167647.html

相关文章

C51点灯学习

#点灯环节 点亮第一个灯 原理:从VCC正极电极过来&#xff0c;若碰到的组件是 1&#xff0c;那么就会不亮(因为两个都是高电平),若碰到的组件是 0,则会通过高低电平来促使灯发亮 #include <REGX52.H>void main() {P2 0xFE;//由高往低数(从P27 ~ P20)1111 1110 }让灯交…

网络空间安全(32)Kali MSF基本介绍

前言 Metasploit Framework&#xff08;简称MSF&#xff09;是一款功能强大的开源安全漏洞检测工具&#xff0c;被广泛应用于渗透测试中。它内置了数千个已知的软件漏洞&#xff0c;并持续更新以应对新兴的安全威胁。MSF不仅限于漏洞利用&#xff0c;还包括信息收集、漏洞探测和…

【Rust】枚举和模式匹配——Rust语言基础14

文章目录 1. 枚举类型1.2. Option 枚举 2. match 控制流结构2.1. match 对绑定值的匹配2.2. Option<T> 的匹配2.3. 通配模式以及 _ 占位符 3. if let 控制流4. 小测试 1. 枚举类型 枚举&#xff08;enumerations&#xff09;&#xff0c;也被称作 enums。枚举允许你通过…

【虚幻C++笔记】引擎源码下载及编译步骤

目录 1.在GitHub上访问虚幻引擎源代码2.安装Visual Studio 20223.解压完成以后&#xff0c;打开源码的根目录&#xff0c;选择Setup.bat运行4.选择GenerateProjectFiles.bat运行,生成uE5.sln文件&#xff0c;点击这个文件打开项目5.设置编译的选项&#xff0c;选择DevelopmentE…

XSS跨站脚本攻击

1、什么是XSS攻击 XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;为了避免与css层叠样式表名称冲突&#xff0c;所以改为xss&#xff0c;是最常见的web应用程序安全漏洞之一。它指的是恶意攻击者往web页面里插入恶意html代码&#xff08;JavaS…

UI-APP---基于HBuilder X的微信小程序

目录 概要 Uni-app 和 HBuilderX 的关系 技术名词解释 ui-app: 概念&#xff1a; 核心特点&#xff1a; 技术细节 基本步骤&#xff1a; 开发流程 项目功能分析&#xff1a; ①首页包括公共头部、导航栏、轮播图、视频列表区域。 ②视频详情页包括公共头部区域、视频详情区域、…

AGI大模型(7):提示词应用

1 生成数据 LLM具有⽣成连贯⽂本的强⼤能⼒。使⽤有效的提示策略可以引导模型产⽣更好、更⼀致和更真实的响应。LLMs还可以特别有⽤地⽣成数据,这对于运⾏各种实验和评估⾮常有⽤。例如,我们可以使⽤它来为情感分类器⽣成快速样本,如下所示: 提示: ⽣成10个情感分析的范…

汽车感性负载-智能高边钳位能量计算

随着汽车电子技术的发展&#xff0c;新的电子电气架构下&#xff0c;越来越多的执行部件在车身出现&#xff0c;比如电磁阀、风机、水泵、油泵、雨刮继电器等常用的执行器&#xff0c; 它们一般都表现为感性特点。驱动这些负载的最简单和最常见的方法是将它们连接到高边侧开关(…