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.hqwc.cn/news/492083.html

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

相关文章

nginx之状态页 日志分割 自定义图表 证书

5.1 网页的状态页 基于nginx 模块 ngx_http_stub_status_module 实现&#xff0c;在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module&#xff0c;否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态 server{…

【计算机科学引论 Computing Essentials 2021】【名词术语】【第7章】

Computing Essentials Chapter 7: Secondary Storage 二级存储 MATCHING Match each numbered item with the most closely related lettered item. Write your answers in the spaces provided. Choices a. DVD (Digital Versatile Disc) b. file compression c. hi-def…

UE5 文字游戏(1) 仅UI截图转换为texture2d(适用于window端)

目录 需求 思路 1.截图并读取到本地 2.本地读取图片并转换为纹理2d 效果展示 找了好多的解决办法&#xff0c;都不管用。这个算是折中的。 需求 将当前的用户控件&#xff08;ui&#xff09;截图下来&#xff0c;并赋值到一个texture2d上。 我的需求&#xff1a;文字游戏…

matlab simulink变压器温度仿真

1、内容简介 略 48-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 matlab simulink变压器温度仿真_哔哩哔哩_bilibili 4、参考论文 略 大型油浸风冷变压器绕组温度场分析_高原 基于顶层油温的变压器绕组热点温度计算改进模型_陈伟根 基于热电类比理论的油浸式电…

Oracle内存计算应用模式

前言 内存计算是利用内存来加速数据访问和应用的性能&#xff0c;并降低应用开发复杂度的技术。近十年来&#xff0c;随着软硬件技术的发展和用户需求的成熟&#xff0c;内存计算技术已经得到了广泛地应用。 Oracle在内存计算领域具有非常重要的地位&#xff0c;这主要得益于…

【JavaEE】_HttpServlet类

目录 1. init方法 2. destory方法 3. service方法 4. servlet生命周期 前文已经提及到&#xff1a;servlet是tomcat提供的&#xff0c;用于操作HTTP协议的一组API&#xff0c;可以将这组API理解为HTTP服务器的框架&#xff1b; 编写一个servlet程序&#xff0c;往往都要继…

怎么样避免被企业裁掉呢?

在当前经济环境下&#xff0c;许多企业纷纷选择裁员以降低成本、提升效益。面对这一现象&#xff0c;员工如何避免成为裁员风波中的牺牲品呢&#xff1f;本文将从多个角度为您提供应对策略。 首先&#xff0c;要了解企业裁员的背景和原因。金融危机、行业变革、市场竞争等外部…

青团社:亿级灵活用工平台的云原生架构实践

作者&#xff1a;杨磊 青团社是国内领先的一站式灵活用工招聘服务企业&#xff0c;灵活用工行业的 Top1。青团社于 2013 年在杭州成立&#xff0c;业务已经覆盖全国&#xff0c;在行业深耕 10 年。我的分享将分为以下三部分&#xff1a; 青团社架构演进的历程青团社如何实现云…

您没有安装最新版本QQ,请先下载 并安装,登录更快更安全。

问题 您没有安装最新版本QQ&#xff0c;请先下载 并安装&#xff0c;登录更快更安全。 详细问题 笔者进行android开发&#xff0c;按照官网步骤操作&#xff0c;实现android 绑定QQ登录&#xff0c;跳至QQ页面报错。 解决方案 在App的AndroidManifest.xml添加 <queries…

llm的inference(二)

文章目录 Tokenizer分词1.单词分词法2.单字符分词法3.子词分词法BPE(字节对编码&#xff0c;Byte Pair Encoding)WordPieceUnigram Language Model(ULM) embedding的本质推理时的一些指标参考链接 Tokenizer 在使用模型前&#xff0c;都需要将sequence过一遍Tokenizer&#xf…

【蓝桥杯省赛真题25】python密室逃脱游戏 青少年组蓝桥杯比赛python编程省赛真题解析

目录 python密室逃脱游戏 一、题目要求 1、编程实现 2、输入输出

FL Studio21升级至国际完整版详细步骤准备工作

一、准备工作 备份项目文件&#xff1a;在升级之前&#xff0c;请务必备份您在FL Studio中的所有项目和重要数据。这可以通过将项目文件夹复制到外部存储设备或云存储中来实现。检查系统要求&#xff1a;确保您的计算机满足FL Studio国际完整版的系统要求。这包括操作系统版本…