Qt QWiget 实现简约美观的加载动画 第三季

😃 第三季来啦 😃 这是最终效果:
在这里插入图片描述
只有三个文件,可以直接编译运行

//main.cpp
#include "LoadingAnimWidget.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QGridLayout>
int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget w;w.setWindowTitle("加载动画 第三季");QGridLayout * mainLayout = new QGridLayout;auto* anim1= new RippleWave;mainLayout->addWidget(anim1,0,0);auto* anim2 = new SlinkyCircle;mainLayout->addWidget(anim2,0,1);auto * anim3 = new ZoomingBalls;mainLayout->addWidget(anim3,1,0);auto* anim4 = new SpotFoldCircle;mainLayout->addWidget(anim4,1,1);w.setLayout(mainLayout);w.show();anim1->start();anim2->start();anim3->start();anim4->start();return a.exec();
}
//LoadingAnimWidget.cpp
#include "LoadingAnimWidget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
LoadingAnimBase::LoadingAnimBase(QWidget* parent):QWidget(parent){mAnim.setPropertyName("angle");mAnim.setTargetObject(this);mAnim.setDuration(2000);mAnim.setLoopCount(-1);//run forevermAnim.setEasingCurve(QEasingCurve::Linear);setFixedSize(200,200);mAngle = 0;
}
LoadingAnimBase::~LoadingAnimBase(){}
void LoadingAnimBase::exec(){if(mAnim.state() == QAbstractAnimation::Stopped){start();}else{stop();}
}
void LoadingAnimBase::start(){mAnim.setStartValue(0);mAnim.setEndValue(360);mAnim.start();
}
void LoadingAnimBase::stop(){mAnim.stop();
}
qreal LoadingAnimBase::angle()const{ return mAngle;}
void LoadingAnimBase::setAngle(qreal an){mAngle = an;update();
}SlinkyCircle::SlinkyCircle(QWidget* parent):LoadingAnimBase (parent){mAnim.setEasingCurve(QEasingCurve::InOutCubic);
}
void SlinkyCircle::paintEvent(QPaintEvent *event){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(Qt::NoPen);//画圆弧painter.setBrush(Qt::NoBrush);const int x = this->width();const int y = this->height();QPen pen("black");pen.setCapStyle(Qt::RoundCap);pen.setWidth(x/20);painter.setPen(pen);painter.translate(x/2,y/2);static const qreal spanAngle = 90;//mAngle<=45,要把弧线拉伸出来static const qreal shrinkAngle = 360 - spanAngle;//mAngle==315时,要把弧线收缩起来auto arcRect = this->rect().adjusted(x/5,y/5,-x/5,-y/5);arcRect.translate(-x/2,-y/2);static const int direction = -1;//顺时针if(mAngle < spanAngle){painter.drawArc(arcRect,90 * 16,mAngle * 16 * direction);}else{//弧长是固定的//40 - 320 --> 320 , 280 --> 320if(mAngle > shrinkAngle){painter.drawArc(arcRect,90 * 16,-(360-mAngle)*16 * direction);}else{//我转动的角度是当前角度 - 拉伸门槛,因为有收尾的不动的时间段,占据了一段角度,所以要把转动的角度拉伸一些,//这个比例就是 (360-spanAngle) / (shrinkAngle - spanAngle)const auto delta = (mAngle - spanAngle) * (360-spanAngle) / (shrinkAngle - spanAngle);painter.rotate(-delta * direction);painter.drawArc(arcRect,90 * 16,spanAngle * 16 * direction);}}}
ZoomingBalls::ZoomingBalls(QWidget* parent):LoadingAnimBase (parent){}void ZoomingBalls::paintEvent(QPaintEvent *event){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(Qt::NoPen);//这里可以设置小球的颜色,也可以改成类的成员static const QStringList colorList{"black","black","black","black","black"};const int x = width();const int y = height();const qreal r = x/24;    //小球的半径const qreal rmax = x/10;  //小球最大半径const qreal alphaSpace = 0.8; //小球颜色变化范围static const int startAngle[5] = {0,45,90,135,180};//五个小球开始变化时间点painter.translate(x/6,y/2);for(int i = 0;i < colorList.size();++i){const auto start = startAngle[i];qreal delta = mAngle - start;QColor background = colorList[i];if(delta > 0 && delta < 180){if(delta > 90) delta = 180 - delta;qreal ratio = delta/ 90.0;qreal alpha = 1- ratio *alphaSpace;qreal radius = r + ratio * (rmax - r);background.setAlphaF(alpha);painter.setBrush(QBrush(background));painter.drawEllipse(QPointF(0,0),radius,radius);}else{//不变painter.setBrush(QBrush(background));painter.drawEllipse(QPointF(0,0),r,r);}painter.translate(x/6.0,0);}
}
SpotFoldCircle::SpotFoldCircle(QWidget* parent):LoadingAnimBase (parent){}void SpotFoldCircle::paintEvent(QPaintEvent *event){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(Qt::NoPen);painter.setBrush(QBrush(QColor("black")));static const int startAngle[5] = {0,15,28,40,50}; //小球开始转动的开始时间点static const int restAngle = 360 - startAngle[4]; //小球休息的时间点static const qreal angleStretch = 360.0 / (360 - startAngle[4]); //角度拉伸比例const int x = this->width();const int y = this->height();painter.translate(x/2,y/2);const int radius = x / 16;//小球的半径static const qreal ratioList[5] = {1,0.8,0.64,0.512,0.41}; //小球半径比例列表 ,很明显,小球越来越小for(int i = 0;i < 5;++i){const int start = startAngle[i];const qreal r = radius * ratioList[i];qreal delta = mAngle - start;if(delta > 0 && delta < restAngle){ //要转动起来painter.rotate(delta * angleStretch);painter.drawEllipse(QPointF(0,-y/2 + radius*2),r,r);painter.rotate(-delta * angleStretch);}else{ //停在原地painter.drawEllipse(QPointF(0,-y/2 + radius*2),r,r);}}
}
RippleWave::RippleWave(QWidget* parent):LoadingAnimBase (parent){}void RippleWave::paintEvent(QPaintEvent *event){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setBrush(Qt::NoBrush);QPen pen("black");pen.setWidth(3);//每层波浪的生命周期是6个单位,一共有八层,每层开始时间是前一层波浪的一个单位之后,时间共分为14个单位static const int arr[8] = {10,15,22,31,42,55,70,87};//波浪的半径static const qreal unit = 360.0 / 14;static const qreal startArr[8] = {0,unit,unit*2 , unit*3 ,unit*4,unit*5,unit*6,unit*7};static const qreal lifeSpan = unit*6;const int x = this->width();const int y = this->height();painter.translate(x/2,y/2);for(int i = 0;i < sizeof(arr) / sizeof(int);++i){const auto start = startArr[i];const auto delta = mAngle - start;qreal alpha = 1;if(delta > 0 && delta < lifeSpan){if(delta < unit*2) alpha = delta / (unit*2);if(delta > unit*4) alpha = (lifeSpan - delta) / (unit*2);QColor c("black");c.setAlphaF(alpha);pen.setColor(c);painter.setPen(pen);painter.drawEllipse(QPointF(0,0),arr[i],arr[i]);}else{//什么都不用做}}
}
//LoadingAnimWidget.h
#ifndef LOADINGANIMWIDGET_H
#define LOADINGANIMWIDGET_H
#include <QPropertyAnimation>
#include <QWidget>
class LoadingAnimBase:public QWidget
{Q_OBJECTQ_PROPERTY(qreal angle READ angle WRITE setAngle)
public:LoadingAnimBase(QWidget* parent=nullptr);virtual ~LoadingAnimBase();qreal angle()const;void setAngle(qreal an);
public slots:virtual void exec();virtual void start();virtual void stop();
protected:QPropertyAnimation mAnim;qreal mAngle;
};
class SlinkyCircle:public LoadingAnimBase{//可以伸缩的管子,绕着中心转动,就像弹簧圈,英语叫做slinky,查了好久才查到这个单词,有点强迫症😂Q_OBJECT
public:explicit SlinkyCircle(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent *event);
};class ZoomingBalls:public LoadingAnimBase{//五个小球,每个依次变大Q_OBJECT
public:explicit ZoomingBalls(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent *event);
};class SpotFoldCircle:public LoadingAnimBase{//五个小球绕中心旋转,可以折叠在一起Q_OBJECT
public:explicit SpotFoldCircle(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent *event);
};class RippleWave:public LoadingAnimBase{//8层波纹,从中间逐渐向外变亮,然后变暗Q_OBJECT
public:explicit RippleWave(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent *event);
};#endif // LOADINGANIMWIDGET_H

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

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

相关文章

设计并实现一个并发安全的LRU(Least Recently Used,最近最少使用)缓存结构

文章目录 前言实战演示写在最后 前言 相信很多人都使用过LinkedHashMap&#xff0c;LinkedHashMap中的removeEldestEntry可以删除老旧的元素&#xff0c;我们可以以此来实现一个LRU缓存结构&#xff0c;并结合java中JUC包中的各种多线程锁机制来保证多线程安全。 以下是我遇见…

【前端素材】推荐优质后台管理系统Dashmin平台模板(附源码)

一、需求分析 后台管理系统在多个层次上提供了丰富的功能和细致的管理手段&#xff0c;帮助管理员轻松管理和控制系统的各个方面。其灵活性和可扩展性使得后台管理系统成为各种网站、应用程序和系统不可或缺的管理工具。 后台管理系统是一种具有多层次结构的软件系统&#xf…

邀请函 | 2024年数据技术嘉年华集结号已吹响,期待您参会!

龙腾四海内&#xff0c;风云际会时&#xff0c;2024年中国数据嘉年华如约而至。从起初小范围的网友聚会&#xff0c;到如今面向全国各地从业者、爱好者的年度集会&#xff0c;纵使岁月更迭&#xff0c;我们初心依旧。我们在各自最好的年华里共同见证了中国数据库行业的蓬勃发展…

Linux下的IO多路复用

文章目录 一. IO的概念和分类1. IO操作的原理&#xff1a;二. I/O多路复用使用场景和作用1. 问题&#xff1a; 一台网络服务器需要接收100台客户端的连接和数据通信&#xff0c;应该如何设计和实现&#xff1f;2. I/O多路复用机制&#xff1a; 三. Select poll epollselectpoll…

【前端素材】推荐优质后台管理系统Modernize平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理和控制网站、应用程序或系统后台操作的软件工具&#xff0c;通常由授权用户&#xff08;如管理员、编辑人员等&#xff09;使用。它提供了一种用户友好的方式来管理网站或应用程序的内容、用户、数据等方面的操作&#xff0c;并且通常…

光学3D表面轮廓仪微纳米三维形貌一键测量

光学3D表面轮廓仪(白光干涉仪)利用白光干涉原理&#xff0c;以0.1nm分辨率精准捕捉物体的表面细节&#xff0c;实现三维显微成像测量&#xff0c;被广泛应用于材料学领域的研究和应用。 了解工作原理与技术 材料学领域中的光学3D表面轮廓仪&#xff0c;也被称为白光干涉仪&am…

SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton 在继续深入探讨 SmartInitializingSingleton接口之前&#xff0c;让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE&#xff08;Java Enterprise Edition&#xff09;全栈&#xff08;full-stack&#x…

力扣 724. 寻找数组的中心下标

思路&#xff1a; 创建两个变量sum和sum1&#xff0c;sum代表左边元素的和&#xff0c;sum1代表右边元素的和 然后假设从数组下标0开始&#xff0c;一直到最后一个作为中心下标 如果sumsum1&#xff0c;返回此时的中心下标 如果所有下标循环完了&#xff0c;发现没有return…

Apipost 数据模型功能API数据重复利用起来

在Apipost数据模型中用户可以预先创建多个数据模型&#xff0c;并在API设计过程中重复利用这些模型来构建API 创建数据模型 在左侧导航点击「数据模型」-「新建数据模型」在右侧工作台配置数据模型参数 引入数据模型 在API设计预定义响应期望下点击引用数据模型&#xff0c;…

操作系统——处理机调度

文章目录 进程调度0.概念1.调度分类高级调度低级调度中级调度七状态模型调度对比 2.进程调度进程调度的时机进程调度的方式进程的切换方式调度器/调度程序闲逛进程 3. 调度算法的评价指标CPU利用率系统吞吐量周转时间等待时间响应时间 4. 调度算法先来先服务(FCFS)短作业优先(S…

【软件测试】--功能测试1

一、测试介绍 什么是软件&#xff1f; 控制计算机硬件工作的工具。 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 软件测试的目的&#xff1f; 减少软件缺陷&#xff0c;保证软件质量。 测试主流技能 1、功能测试 2、自动化测试 3、接口测试 4、性能测试 ​…

MySQL-事务,properties文件解析,连接池

1.事务机制管理 1.1 Transaction事务机制管理 默认情况下是执行一条sql语句就保存一次&#xff0c;那么比如我们需要三条数据同时成功或同时失败就需要开启事务机制了。开启事务机制后执行过程中发生问题就会回滚到操作之前&#xff0c;相当于没有执行操作。 1.2 事务的特征 事…

【初始RabbitMQ】延迟队列的实现

延迟队列概念 延迟队列中的元素是希望在指定时间到了之后或之前取出和处理消息&#xff0c;并且队列内部是有序的。简单来说&#xff0c;延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列使用场景 延迟队列经常使用的场景有以下几点&#xff1a; 订单在十分…

Anaconda下安装torch-geometric

主要流程参考&#xff1a;https://blog.csdn.net/weixin_45671036/article/details/130617637 https://blog.csdn.net/weixin_43756314/article/details/130225038?ops_request_misc&request_id&biz_id102&utm_term%E5%80%9F%E5%8A%A9anaconda%20%E5%AE%89%E8%A3%…

配置vscode,使其可以运行C++11特性的代码(如vector)

配置vscode&#xff0c;使其可以运行C11特性的代码 封面引用自配置教程的B站视频&#xff0c;非常详细的视频&#xff0c;感谢视频作者的贡献。 文章目录 配置vscode&#xff0c;使其可以运行C11特性的代码Step 1: 基础配置Step 2: 调整Code Runner的配置Step 3: 更改tasks.jso…

一文7个步骤教你搭建测试web测试项目实战环境

​今天小编&#xff0c;给大家总结下web 测试实战的相关内容&#xff0c;一起来学习下吧&#xff01; web项目实战可按顺序依次为&#xff1a;【搭建测试环境】、【需求评审】、【编写测试计划】、【分析测试点.编写测试用例】、【用例评审】、【执行用例提bug】、【测试报告】…

undo日志详解

一、undo日志介绍 上一节详细的说了redo日志&#xff0c;redo日志的功能就是把增删改操作都记录着&#xff0c;如果断电导致内存中的脏页丢失&#xff0c;可以根据磁盘中的redo日志文件进行恢复。redo日志被设计出来是为了保证数据库的持久性&#xff0c;undo日志设计出来是为…

AI 绘画:人工智能绘画之美

人工智能&#xff08;AI&#xff09;是当今科技领域的热门话题&#xff0c;它不仅可以帮助我们解决各种复杂的问题&#xff0c;还可以创造出令人惊叹的艺术作品。AI 绘画是一种利用 AI 技术生成图像的方法&#xff0c;它可以模仿不同的风格、主题和技巧&#xff0c;甚至可以创造…

Qt Linux下调用OpenGL的glu.h报错:error: GL/glu.h: No such file or directory

Qt Linux下调用OpenGL的glu.h报错&#xff1a;error: GL/glu.h: No such file or directory 引言一、问题描述二、解决方案三、解决过程记录3.1 定位问题3.2 尝试使用yum命令安装3.3 从网上下载到本地进行安装 引言 在Windows上正常运行的OpenGL程序&#xff0c;到Linux下突然…

cuda学习笔记(2)

一 专业名词 1 分支断定 2 一致性和同一性 3 常见名词汇总 4 加速比 二 GPU架构构述 GPU就是将cpu的数据存储单元去掉&#xff0c;也就是保留执行单元&#xff0c;GPU就是多个执行单元 1 GPU设计思路&#xff0c;指令流共享&#xff0c;同时执行&#xff0c;数据切分成小块 …