Qt QWidget 简约美观的加载动画 第四季

😊 第四季来啦 😊
效果如下:
在这里插入图片描述
只有三个文件,可以直接编译运行的

//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 JellyInBox;mainLayout->addWidget(anim1,0,0);auto* anim2 = new HorizontalDNA;mainLayout->addWidget(anim2,0,1);auto * anim3 = new  LoopedRingWithText;mainLayout->addWidget(anim3,1,0);auto* anim4 = new Radar;mainLayout->addWidget(anim4,1,1);w.setLayout(mainLayout);w.show();anim1->start();anim2->start();anim3->start();anim4->start();return a.exec();
}
//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 JellyInBox:public LoadingAnimBase{//一个会伸缩的果冻在一个小盒子里面,一开始拉伸,然后移动,然后收缩
public:explicit JellyInBox(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent *event);
};
class HorizontalDNA:public LoadingAnimBase{//两根水平方向的小球链,螺旋滚动,像DNA双分子链
public:explicit HorizontalDNA(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent*);
private:void getPosYAlphaScale(const int amplitude,const qreal & offset,qreal & y,qreal & alpha,qreal & scale);//根据原始偏移获取当前时间点下的y轴坐标,透明度,和缩放比例
};
class LoopedRingWithText:public LoadingAnimBase{//外面有三圈圆环转动,中间有一个高亮的灯光从左向右移动照亮字符串的一部分
public:explicit LoopedRingWithText(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent*);
};
class Radar:public LoadingAnimBase{//像一个雷达一样扫描,等待耗时操作的结束
public:explicit Radar(QWidget* parent = nullptr);
protected:void paintEvent(QPaintEvent*);
};#endif // LOADINGANIMWIDGET_H
//LoadingAnimWidget.cpp
#include "LoadingAnimWidget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QtMath>
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();
}
JellyInBox::JellyInBox(QWidget* parent):LoadingAnimBase (parent){}
void JellyInBox::paintEvent(QPaintEvent *event){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setBrush(Qt::NoBrush);int x = this->width();const int y = this->height();//先画一个盒子QPen pen("black");pen.setWidth(3);painter.setPen(pen);painter.drawRoundedRect(QRectF(1,0.4375*y,x-2,y/8),y/16.0,y/16.0);//画果冻pen.setCapStyle(Qt::RoundCap);painter.setBrush(Qt::NoBrush);const int gap = 4;//果冻和盒子之间的间距const int boxGap = 1;//盒子的外间距const qreal jh = y/8 - gap*2;//果冻高度pen.setWidthF(jh);painter.setPen(pen);painter.translate(boxGap + gap + jh/2,y/2);x -= (boxGap + gap) * 2 + jh;//可以移动的x范围是总宽度 - 两边的两个间距 - 笔头厚度const qreal maxw = 0.4*x;//最大的果冻宽度int jx = 0;qreal jw = 0;if(mAngle < 90){jw = maxw * mAngle / 90;}else if(mAngle < 270){jw = maxw;jx = (x - maxw) * (mAngle - 90) / 180;}else{jx = x - maxw + (mAngle - 270) / 90 * maxw;jw = x - jx;}painter.drawLine(jx,0,jx+jw,0);
}
HorizontalDNA::HorizontalDNA(QWidget* parent):LoadingAnimBase (parent){mAnim.setDuration(5000);
}
void HorizontalDNA::getPosYAlphaScale(const int amplitude,const qreal & offset,qreal & y,qreal & alpha,qreal & scale){static const qreal a = 2*3.1415926 / 360;//qreal x = a*mAngle + offset;//随着时间的流逝,x变大,y踩着着右边的值,看上去就是右边的小球带动左侧的小球移动//如果要实现左边的小球带动右侧的小球,要这样auto x = -a * mAngle + offset;y = qSin(x);auto tmp = qCos(x); //随着时间的流逝,x变小,当小球向上移动的时候,透明度变小tmp += 1;tmp /= 2;alpha = 1- tmp;scale = alpha / 2 + 0.5;//不要太小了,最小是0.5y *= amplitude;//amplitude就是振幅 sin(x)的振幅是1
}
void HorizontalDNA::paintEvent(QPaintEvent*){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(Qt::NoPen);const int x = width();const qreal radius = x / 20.0;//小球的半径const qreal y = height();const qreal unitx = x / 8.0;//小球的间距painter.translate(unitx,y/2);static const qreal gap = M_PI / 6;static const qreal offsetList[7] = {gap*0,gap*1,gap*2,gap*3,gap*4,gap*5,gap*6};QColor ballColor("black");for(int i = 0;i < 7;++i){qreal bally ,alpha,scale;getPosYAlphaScale(y/6,offsetList[i],bally,alpha,scale);ballColor.setAlphaF(alpha);painter.setBrush(QBrush(ballColor));painter.drawEllipse(QPointF(unitx*i,bally),radius*scale,radius*scale);}static const qreal offsetList2[7] = {gap*6,gap*7,gap*8,gap*9,gap*10,gap*11,0};for(int i = 0;i < 7;++i){qreal bally ,alpha,scale;getPosYAlphaScale(y/6,offsetList2[i],bally,alpha,scale);ballColor.setAlphaF(alpha);painter.setBrush(QBrush(ballColor));painter.drawEllipse(QPointF(unitx*i,bally),radius*scale,radius*scale);}
}
LoopedRingWithText:: LoopedRingWithText(QWidget* parent):LoadingAnimBase(parent){mAnim.setDuration(6000);
}
void  LoopedRingWithText::paintEvent(QPaintEvent*){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);const int x = width();const int y = height();//step0:定义一些颜色变量,也可以改成成员变量static const QColor bright("turquoise");//最亮的圆环颜色static const QColor medium = QColor(bright.red(),bright.green(),bright.blue(),200);static const QColor dim = QColor(bright.red(),bright.green(),bright.blue(),160);//step1:画一个深色的背景painter.setPen(Qt::NoPen);painter.setBrush(QBrush(QColor("dimgray")));painter.drawRoundedRect(this->rect(),x/12,x/12);//step2:画最外面的两个圆环painter.translate(x/2,y/2);QPen pen(dim);pen.setWidth(4);pen.setCapStyle(Qt::RoundCap);painter.setPen(pen);const auto rect1 = QRectF(-0.45*x,-0.45*y,0.9*x,0.9*y);static const qreal start = 30;static const qreal span = 120;auto ang = mAngle;painter.rotate(ang);painter.drawArc(rect1,start * 16,span * 16);painter.drawArc(rect1,(start+180) *16,span * 16);painter.resetTransform();//step3:画中间的两个圆环pen.setColor(medium);painter.setPen(pen);painter.translate(x/2,y/2);const auto rect2 = QRectF(-0.375*x,-0.375*y,0.75*x,0.75*y);if(ang > 180) ang -= 180;//周期改成180,比外面的转的快一倍painter.rotate(-2*ang);painter.drawArc(rect2,start * 16,span * 16);painter.drawArc(rect2,(start + 180)*16,span*16);painter.resetTransform();//step4:画内部的4个圆环pen.setColor(bright);painter.setPen(pen);painter.translate(x/2,y/2);const auto rect3 = QRectF(-0.3*x,-0.3*y,0.6*x,0.6*y);ang = mAngle;static const qreal t3 = 120;//周期改成120,比中间的更快while(ang > t3) ang -= t3;painter.rotate( ang * 90 / t3);//四个圆环转过90度的时候也就是长短交替一次,要把这个转过的角度乘以调整系数:90/120qreal start0 = 15 + (90-15) * (ang / t3);//开始的时候上方圆环起点在15度,变化到90度时弧长为0qreal span0 = 180 - 2*start0;if(span0 > 0){//第一组painter.drawArc(rect3,start0*16 , span0*16);painter.drawArc(rect3,(start0+180)*16,span0*16);}start0 = -75 * (ang / t3);//开始的时候,右侧圆环起点是0,弧长为0,它的最大弧长时刻,起点在-75度span0 = -start0 * 2;if(span0 > 0){//第二组painter.drawArc(rect3,start0*16,span0*16);painter.drawArc(rect3,(start0+180)*16,span0*16);}painter.resetTransform();QFont font("Microsoft YaHei",12,4);painter.setFont(font);QFontMetrics fm(font);static const QString text("Loading...");qreal textw = fm.horizontalAdvance(text);qreal texth = fm.height();QPainterPath pp;pp.addText(QPointF( (x - textw)/2,0.5*y + texth/4),font,text);painter.setClipPath(pp);painter.setPen(Qt::NoPen);painter.setBrush(QBrush(dim));//step5: 先画一个淡色的文本painter.drawRect(rect());//step6: 最后一步啦,画一个圆灯光painter.translate(0,0.5*y);const qreal unit = x / 360.0;QRadialGradient grad(QPointF(mAngle*unit,0),texth);grad.setColorAt(0,bright);grad.setColorAt(1,dim);painter.setBrush(grad);painter.drawEllipse(QPointF(mAngle * unit,0),texth,texth);
}
Radar::Radar(QWidget* parent):LoadingAnimBase(parent){}
void Radar::paintEvent(QPaintEvent*){QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);//step1: 画一个淡色背景,很多简约的界面都需要透明背景,这一步可以删掉painter.setPen(Qt::NoPen);painter.setBrush(QBrush("deepskyblue"));const int x = width();const int y = height();painter.drawRoundedRect(rect(),x/12,x/12);//step2: 画一个雷达painter.translate(x/2,y/2);QConicalGradient gra(QPointF(0,0),45);static const QColor color0("white");static const QColor color1(color0.red(),color0.green(),color0.blue(),100);gra.setColorAt(0,color0);gra.setColorAt(0.2,color1);gra.setColorAt(1,"transparent");painter.setBrush(gra);painter.rotate(mAngle);const auto rect = QRectF(-x/4,-y/4,x/2,y/2);painter.drawPie(rect,45*16,90*16);}

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

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

相关文章

ARM Cortex-X5 传言表现不佳,高功率浪涌和低多核分数影响即将推出的核心设计

ARM 的新 Cortex-X5 设计似乎遇到了问题&#xff0c;有新的传言称&#xff0c;超级核心在提高时钟速度时会经历严重的高功耗&#xff0c;并且当最大功率限制降低时&#xff0c;多核性能会下降。虽然这对高通来说可能不是问题&#xff0c;因为据说其 Snapdragon 8 Gen 4 采用定制…

同样的故事,三星靠中国以外的市场称霸,国产手机靠国内崛起

2023年全球市场的折叠手机销量增速已大幅下降至25%&#xff0c;而且增长主要来自中国市场&#xff0c;由此形成一个特殊的现象&#xff0c;那就是中国手机依靠本土市场崛起&#xff0c;三星则依靠占领中国以外的市场称霸全球。 数据显示2023年全球市场的折叠手机销量为1590万部…

Arduino中安装ESP32网络抽风无法下载 暴力解决办法 python

不知道什么仙人设计的arduino连接网络部分&#xff0c;死活下不下来。&#xff08;真的沙口&#xff0c;第一次看到这么抽风的下载口&#xff09; 操作 给爷惹火了我踏马解析json选zip直接全部下下来 把这个大家的开发板管理地址下下来跟后面python放在同一目录下&#xff0c…

liunx前后端分离项目部署

文章目录 1、nginx的安装和自启动2.nginx负载均衡3.前后端项目部署-后端部署4.前后端项目部署-前端部署 1、nginx的安装和自启动 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel1.安装我们nginx所需要的依赖 wget http://nginx.org/download/nginx-1.…

【MySQL面试复习】索引创建的原则有哪些?

系列文章目录 在MySQL中&#xff0c;如何定位慢查询&#xff1f; 发现了某个SQL语句执行很慢&#xff0c;如何进行分析&#xff1f; 了解过索引吗&#xff1f;(索引的底层原理)/B 树和B树的区别是什么&#xff1f; 什么是聚簇索引&#xff08;聚集索引&#xff09;和非聚簇索引…

MySQL锁三部曲:临键、间隙与记录的奇妙旅程

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 MySQL锁三部曲&#xff1a;临键、间隙与记录的奇妙旅程 前言临键锁的奥秘间隙锁记录锁 前言 在数据库世界中&#xff0c;锁是维护数据完整性的一种关键机制。而MySQL中的临键锁、间隙锁和记录锁则是锁…

matlab倒立摆小车LQR控制动画

1、内容简介 略 54-可以交流、咨询、答疑 2、内容说明 略 摆杆长度为 L&#xff0c;质量为 m 的单级倒立摆(摆杆的质心在杆的中心处)&#xff0c;小车的质量为 M。在水平方向施加控制力 u&#xff0c;相对参考系产生位移为 y。为了简化问题并且保其实质不变&#xff0c;忽…

快速启动-后台管理系统

目录 Gitee人人开源 后端快速启动 1.clone仓库到本地 2.初始化数据库 3.更改数据库连接 4.启动项目验证 前端快速启动 1.克隆仓库 2.vsCode打开 3.控制台npm install 4.验证测试 时代已然不同&#xff0c;后台管理也可以使用脚手架方式快速启动。 Gitee人人开源 地…

QT GUI编程常用控件学习

1 GUI编程应该学什么 2 QT常用模块结构 QtCore: 包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用 QtGui: 包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类 QtWidgets: 包含了一些列创建桌面应用的UI元素…

InnoDB中的索引类型以及为什么使用

InnoDB中的索引类型&#xff1f; InnoDB存储引擎支持两种常见的索引数据结构&#xff1a;B树索引、Hash索引&#xff0c;其中B树索引是目前关系型数据库系统中最常见、最有效的索引。 数据库中的B树索引分为聚集索引和非聚集索引。聚集索引就是按照每张表的主键构造一个B树&am…

HuggingFists系统功能介绍(2)--数据源账号

数据源 再次&#xff0c;我们进入“数据源”管理模块。该模块用于管理我们在进行数据处理或分析时所需要的所有数据源。在定义任何的数据流程读写工作之前&#xff0c;必须先通过数据源管理模块创建出对应的数据源。数据源可以是我们需要进行数据处理时&#xff0c;原始数据所在…

做接口测试的流程一般是怎么样的?UI功能6大流程、接口测试8大流程这些你真的全会了吗?

在讲接口流程测试之前&#xff0c;首先需要给大家申明下&#xff1a;接口测试对于测试人员而言&#xff0c;非常非常重要&#xff0c;懂功能测试接口测试&#xff0c;就能在企业中拿到一份非常不错的薪资。 这么重要的接口测试&#xff0c;一般也是面试笔试必问。为方便大家更…