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

这次和大家分享6个非常清爽的加载动画.
😊 效果如下 😊
在这里插入图片描述
一共三个文件 , 可以直接编译运行的呢

//main.cpp
#include "LoadingAnimWidget.h"
#include <QApplication>
#include <QGridLayout>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("加载动画 第9季");
    QGridLayout * mainLayout = new QGridLayout;

    auto* anim1 = new ThreeRevolvingBalls;
    mainLayout->addWidget(anim1,0,0);

    auto* anim2 = new InfinityLoop;
    mainLayout->addWidget(anim2,0,1);

    auto* anim3 = new Fingerprint;
    mainLayout->addWidget(anim3,0,2);

    auto* anim4 = new Solitary9Swords;
    mainLayout->addWidget(anim4,1,0);

    auto* anim5 = new LithiumWave;
    mainLayout->addWidget(anim5,1,1);

    auto* anim6 = new DotInCircle;
    mainLayout->addWidget(anim6,1,2);

    w.setLayout(mainLayout);
    w.show();
    anim1->start();
    anim2->start();
    anim3->start();
    anim4->start();
    anim5->start();
    anim6->start();
    return a.exec();
}

//LoadingAnimWidget.h
#ifndef LOADINGANIMWIDGET_H
#define LOADINGANIMWIDGET_H
#include <QPropertyAnimation>
#include <QWidget>
class LoadingAnimBase:public QWidget
{
    Q_OBJECT
    Q_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 ThreeRevolvingBalls:public LoadingAnimBase{
public:
    ThreeRevolvingBalls(QWidget* parent = nullptr);//三个绕着中心店旋转和缩放的球
protected:
    void paintEvent(QPaintEvent*);
};

class InfinityLoop:public LoadingAnimBase{//一个无穷大标志的双环,上面有一个行星在无尽地绕行
public:
    InfinityLoop(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class Fingerprint:public LoadingAnimBase{//一个多层的转动的圆环,像变幻的指纹
public:
    Fingerprint(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class Solitary9Swords:public LoadingAnimBase{//六根竖线旋转,中间变幻出18根竖线,有点像独孤九剑在空中的残影
public:
    Solitary9Swords(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class LithiumWave:public LoadingAnimBase{//中间是相连的三个小球,它们的转动引起周围波浪发散出去,类似锂离子的三个质子振动
public:
    LithiumWave(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class DotInCircle:public LoadingAnimBase{//一个圆圈内部有一个小球绕着内侧轨道转动,模仿的小米手机浏览器的加载动画
public:
    DotInCircle(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};

#endif
//LoadingAnimWidget.cpp
#include "LoadingAnimWidget.h"
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QtMath>
#include <QRandomGenerator>
LoadingAnimBase::LoadingAnimBase(QWidget* parent):QWidget(parent){
    mAnim.setPropertyName("angle");
    mAnim.setTargetObject(this);
    mAnim.setDuration(2000);
    mAnim.setLoopCount(-1);//run forever
    mAnim.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();
}
ThreeRevolvingBalls::ThreeRevolvingBalls(QWidget* parent ):LoadingAnimBase(parent){}
void ThreeRevolvingBalls::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    painter.setPen(Qt::NoPen);
    static const QColor colorList[3] = {"cadetblue" , "coral" , "hotpink"};
    painter.translate(x/2,y/2);
    painter.rotate(mAngle);
    for(int i = 0;i < 3;++i){
        painter.setBrush(QBrush(colorList[i]));
        const auto r = (0.1+0.03*qSin(M_PI/60*mAngle))*y;
        painter.drawEllipse(QPointF(0,-y/6),r,r);
        painter.rotate(120);
    }
}
InfinityLoop::InfinityLoop(QWidget* parent):LoadingAnimBase (parent){}
void InfinityLoop::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    const qreal r = 0.45*x / (1+qSqrt(2));
    static const qreal _sqrt2 = 0.70711;// 1/根号2
    painter.setBrush(Qt::NoBrush);
    painter.translate(x/2,y/2);

    QColor railColor("lightgray");
    railColor.setAlphaF(0.5);
    QPen pen(railColor);
    pen.setWidth(6);
    painter.setPen(pen);

    //先画一个淡色的轨道
    QPainterPath pp;
    pp.moveTo(0,0);
    pp.lineTo(_sqrt2*r,-_sqrt2*r);
    pp.arcTo(QRectF(0.45*x-2*r,-r,2*r,2*r),135,-270);
    pp.lineTo(-_sqrt2*r,-_sqrt2*r);
    pp.arcTo(QRectF(-0.45*x,-r,2*r,2*r),45,270);
    pp.lineTo(0,0);
    painter.drawPath(pp);
    //画一个小火车
    pen.setColor("darkgray");
    painter.setPen(pen);

    static const int totPercent = 30;
    const int rotateAngle = 270;
    if(mAngle < rotateAngle){
        for(int i = 0;i < totPercent;++i){
            qreal percent = mAngle / rotateAngle - 0.01*i;
            int tmp = percent*100;
            percent = tmp/100.0;//精度不要太高,否则起点会有抖动
            if(percent < 0 ) break;
            painter.drawEllipse( pp.pointAtPercent(percent) , 2,2);
        }
    }
    else{
        int left = (360-mAngle)/(360-rotateAngle) * totPercent;
        for(int i = 0;i < left;++i){
            painter.drawEllipse(pp.pointAtPercent(1 - 0.01*i),2,2);
        }
    }
}
Fingerprint::Fingerprint(QWidget* parent):LoadingAnimBase (parent){
    mAnim.setDuration(8000);
}
void Fingerprint::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(Qt::NoBrush);
    QPen pen("darkseagreen");
    pen.setWidth(2);
    pen.setCapStyle(Qt::RoundCap);
    painter.setPen(pen);
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/2);

    static const int loopNum = 12;//12层指纹
    static const int gap = 6;//指纹的间距

    static QList<qreal> spanList;
    if(spanList.size() <= 0){
        for(int i = 0;i < 361;++i)
            spanList.push_back(120+60*qSin(M_PI*2/360*i));
    }

    for(int i = 0;i < loopNum;++i){
        const int r = gap*(i+1);
        const qreal start = mAngle*(i+1);//越往外,速度越快
        const int idx = mAngle;
        painter.drawArc(QRectF(-r,-r,r*2,r*2),start*16,16*spanList[idx]);
    }
}
Solitary9Swords::Solitary9Swords(QWidget* parent):LoadingAnimBase(parent){
    mAnim.setDuration(4000);
}

void Solitary9Swords::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/2);
    painter.setBrush(Qt::NoBrush);
    static const QColor colorList[3] = {"cadetblue" , "lawngreen" , "lightblue"};
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    pen.setWidthF(2);
    if(mAngle < 150){
        const qreal ratio = mAngle / 150;
        for(int i = 0;i < 3;++i){
            qreal speed = ratio;
            if(i == 0) speed =  qPow(ratio,0.4);//最快
            else if(i == 1) speed = qPow(ratio,0.6);
            else if(i == 2) speed = qPow(ratio,0.99);//最慢
            pen.setColor(colorList[i]);
            painter.setPen(pen);
            for(int a = 0;a < 6;a++){
                painter.rotate(60*speed);
                painter.drawLine(0,-0.3*y/2,0,-0.9*y/2);
            }
            painter.resetTransform();
            painter.translate(x/2,y/2);
        }
    }
    else if(mAngle < 210){
        pen.setColor(colorList[2]);
        painter.setPen(pen);
        for(int a = 0; a< 6;a++){
            painter.drawLine(0,-0.3*y/2,0,-0.9*y/2);
            painter.rotate(60);
        }
    }
    else{
        const qreal ratio = (mAngle - 210) / 150;
        pen.setColor(colorList[2]);
        painter.setPen(pen);
        painter.drawLine(0,-0.3*y/2,0,-0.9*y/2);
        for(int i = 0;i < 3;++i){
            qreal speed;
            if(i == 0) speed =  qPow(ratio,0.4);//最快
            else if(i == 1) speed = qPow(ratio,0.6);
            else if(i == 2) speed = qPow(ratio,0.99);//最慢
            pen.setColor(colorList[i]);
            painter.setPen(pen);
            for(int a = 1;a <= 5;++a){
                painter.rotate(60*a+ (360-a*60)*speed);
                painter.drawLine(0,-0.3*y/2,0,-0.9*y/2);
                painter.resetTransform();
                painter.translate(x/2,y/2);
            }
        }
    }
}
LithiumWave::LithiumWave(QWidget* parent):LoadingAnimBase(parent){}
void LithiumWave::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    QPen pen("lightblue");
    pen.setWidth(2);
    painter.setPen(pen);
    painter.setBrush(QBrush("lightblue"));
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/2);
    static const qreal e = 6;//等边三角形的半边长
    static const qreal r = 4; //质子半径
    qreal zoom = 0.5+ 2*qSin(M_PI / 360 * mAngle);
    painter.scale(zoom,zoom);
    painter.rotate(mAngle);

    //画三个质子
    for(int i = 0;i < 3;++i){
        painter.drawEllipse(QPointF(0,-sqrt(3) *2/3*e ) , r,r);
        painter.drawLine(0, -sqrt(3) *2/3*e,e,sqrt(3)*e/3);
        painter.rotate(120);
    }
    //画5层电磁波
    painter.resetTransform();
    painter.translate(x/2,y/2);
    painter.setBrush(Qt::NoBrush);

    for(int i = 0;i < 5;++i){
        const qreal ratio = (mAngle - i*40)/200;
        if(ratio < 0) break;    //最后一层都灭了,后面已经没有波了
        if(ratio > 1) continue;//最外层的不要画了
        qreal wr = x/2*(0.3 + 0.7*ratio);
        QColor c = pen.color();
        qreal opacity = qSin(M_PI*ratio);
        c.setAlphaF(opacity);
        pen.setColor(c);
        painter.setPen(pen);
        painter.drawEllipse(QPointF(0,0),wr,wr);
    }
}
DotInCircle::DotInCircle(QWidget* parent):LoadingAnimBase(parent){}
void DotInCircle::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(Qt::NoBrush);
    QPen pen("lightgray");
    pen.setWidth(4);
    painter.setPen(pen);
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/2);
    painter.drawEllipse(QPointF(0,0),x/4,x/4);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush("darkgray"));
    painter.rotate(mAngle);
    static const qreal r = 8;
    painter.drawEllipse(QPointF(0,-x/4 +r*2),r,r);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器人最短路径规划问题(栅格地图)】基于模拟退火算法求解

代码获取方式&#xff1a;QQ&#xff1a;491052175 或者 私聊博主获取 基于模拟退火算法求解机器人最短路径规划问题&#xff08;栅格地图&#xff09;的仿真结果 仿真结果&#xff1a; 初始解的路径规划图 收敛曲线&#xff1a; 模拟退火算法求解的路径规划图 结论&#xff…

DVWA靶场 Command Injection,高中低

Low 输入ip地址正常显示&#xff0c;尝试加入其他命令 127.0.0.1 & whoami 后面的whoami也执行了 Medium whoami也可以执行 好像&可应用&#xff0c;&&应该是被过滤 High &用不了&#xff0c;应该是过滤了吧 经过尝试&、|都无法用 查看源码后发现有…

GO逃逸分析

内存管理 内存管理主要包括两个动作&#xff1a;分配与释放。逃逸分析就是服务于内存分配的&#xff0c;而内存的释放由GC负责。 栈 在Go语言中&#xff0c;栈的内存是由编译器自动进行分配和释放的&#xff0c;栈区往往存储着函数参数、局部变量和调用函数帧&#xff0c;它…

Java 计算某年份二月的天数

一、实验任务 要求编写一个程序&#xff0c;从键盘输入年份&#xff0c;根据输入的年份计算这一年的2月有多少天。 二、实验内容 三、实验结果 四、实现逻辑和步骤 &#xff08;1&#xff09;使用scanner类实现程序使用键盘录入一个年份。 &#xff08;2&#xff09;使用if语…

百度诉闪速推公司涉“万词霸屏”不正当竞争纠纷案审理结果

交叉口讯 5月13日&#xff0c;江苏省高级人民法院知识产权庭公布百度诉闪推公司涉及“万磁霸屏”不正当竞争纠纷一案审理结果&#xff1a;判决闪推公司应立即停止涉案的不正当竞争行为。 &#xff0c;公司在其公司官网发布声明&#xff0c;消除影响&#xff0c;并赔偿百度经济损…

Pandas DataFrame 基本操作实例100个

Pandas 是一个基于NumPy的数据分析模块&#xff0c;最初由AQR Capital Management于2008年4月开发&#xff0c;并于2009年底开源。Pandas的名称来源于“Panel Data”&#xff08;面板数据&#xff09;和“Python数据分析”&#xff08;data analysis&#xff09;。这个库现在由…

Google Dremel和parquet的复杂嵌套数据结构表征方法解析

转载请注明出处。作者&#xff1a;archimekai 核心参考文献&#xff1a; Dremel: Interactive Analysis of Web-Scale Datasets 文章目录 引言复杂嵌套数据结构的无损表征问题Dremel论文中提出的表征方法parquet备注 引言 Dremel是Google的交互式分析系统。Google大量采用prot…

IDEA POM文件配置profile实现不同环境切换

目录 一、背景 二、实现 2.1创建不同的配置文件 2.2配置POM文件 三、效果 3.1本地使用 2.2线上或者测试环境使用 一、背景 在企业级开发中&#xff0c;为了不影响生产环境的项目运行&#xff0c;一般情况下都会划分生产环境、测试环境、开发环境。不同环境可以配置不同的…

ubuntu安裝Avahi发现服务工具

一、简介 解决设置固定ip后无法连接外网的问题&#xff0c;目前采用动态获取ip&#xff0c;可以不用设置设备的固定IP&#xff0c;直接可以通过域名来访问设备&#xff0c;类似树莓派的连接调试 二、安装 本文使用的是ubuntu23.10.1上安装 1.安装工具 sudo apt install av…

ABAP - SALV教程17 弹窗ALV

SALV可以通过弹窗形式打开在生成SALV实例对象后调用set_screen_popup方法设置成弹出模式 "设置为弹窗模式 go_alv->set_screen_popup( start_column 10end_column 110start_line 5end_line 15). 显示效果 完整代码 SELECT *FROM ekkoINTO TABLE DATA(gt_dat…

使用plasmo框架开发浏览器插件,注入contents脚本和给页面添加UI组件

plasmo&#xff1a;GitHub - PlasmoHQ/plasmo: &#x1f9e9; The Browser Extension Framework plasmo是一个开发浏览器插件的框架&#xff0c;支持使用react和vue等技术&#xff0c;而且不用手动管理manifest.json文件&#xff0c;框架会根据你在框架中的使用&#xff0c;自…

二极管原理及典型应用电路、三极管基本结构及类型状态

目录 二极管原理及典型应用电路 二极管的工作原理 二极管保护电路 二极管整流电路 二极管稳压电路 三极管基本结构及类型状态 三极管基本结构和类型 三极管的 3 种工作状态 二极管原理及典型应用电路 如下图&#xff0c;二极管长成这样。它们通常有一个黑色圆柱体&am…

力扣刷题笔记

力扣206 反转链表 题目描述: 给你单链表的头节点head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[…

抖音视频评论批量下载软件|抖音数据抓取工具

随着业务需求的增长&#xff0c;抖音视频的下载需求也日益增加。传统的方式是通过逐个复制粘贴分享链接来下载视频&#xff0c;这种操作效率低下且耗时费力。为了解决这一问题&#xff0c;我们开发了一款基于C#的抖音视频评论批量下载软件&#xff0c;旨在实现通过关键词自动批…

STM32(5) GPIO(2)输出

1.点亮LED 1.1 推挽接法和开漏接法 要想点亮LED&#xff0c;有两种接法 推挽接法&#xff1a; 向寄存器写1&#xff0c;引脚输出高电平&#xff0c;LED点亮&#xff1b;向寄存器写0&#xff0c;引脚输出低电平&#xff0c;LED熄灭。 开漏接法&#xff1a; 向寄存器写0&…

【大厂AI课学习笔记NO.64】机器学习开发框架

机器学习开发框架本质上是一种编程库或工具&#xff0c;目的是能够让开发人员更容易、更快速地构建机器学习模型。 机器学习开发框架封装了大量的可重用代码&#xff0c;可以直接调用&#xff0c;目的是避免“重复造轮子’大幅降低开发人员的开发难度&#xff0c;提高开发效率…

Spark(2)-基础tranform算子(一)

一、算子列表 编号名称1map算子2flatMap算子3filter算子4mapPartitions算子5mapPartitionsWithIndex算子6keys算子7values算子8mapValues算子9flatMaplValues算子10union算子11reducedByKey算子12combineByKey算子13groupByKey算子14foldByKey算子15aggregateByKey算子16Shuff…

计算机网络-网络安全(一)

1.网络安全威胁和漏洞类型&#xff1a; 窃听 假冒 重放 流量分析 破环完整 病毒 木马 诽谤 非授权访问 拒绝服务 漏洞&#xff1a;物理、软件、不兼容、其他等。 2.网络安全信息数据五大特征&#xff1a; 完整性&…

kettle下载及安装

JDK下载 安装kettle之前需要安装JDK JDK下载链接&#xff1a;JDK下载 配置环境变量&#xff1a; 新建系统变量&#xff1a;变量值为JDK安装路径 Path新增&#xff1a; kettle下载 链接地址&#xff1a;PDI&#xff08;kettle&#xff09; 点击下载 同意 Click here to a…

模拟集成电路设计:Bandgap电路设计及版图实现

模拟集成电路设计 Bandgap电路设计及版图实现 一、目的&#xff1a; 1、熟悉模拟集成电路设计的基本流程&#xff0c;实现Bandgap电路设计&#xff1b; 2、熟悉Linux系统及Cadence Virtuoso icfb设计、仿真软件的使用方法。 二、原理&#xff1a; 1、设计目标&#xff1a;…