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

news2024/12/26 23:33:25

这次和大家分享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);
}

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

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

相关文章

Endnote x9 最快方法批量导入.enw格式文件

按照网上看到的一个方法直接选中所有enw批量拖拽到 All references 附件不行啊&#xff0c; 以为只能写bat脚本方式了 经过一番尝试&#xff0c;惊人的发现拖到下面这个符号的地方就行了&#xff01;&#xff01;&#xff01; 如果不成功的话&#xff0c;可能&#xff1a; 我…

WordPress免费的远程图片本地化下载插件nicen-localize-image

nicen-localize-image&#xff08;可在wordpress插件市场搜索下载&#xff09;&#xff0c;是一款用于本地化文章外部图片的插件&#xff0c;支持如下功能&#xff1a; 文章发布前通过编辑器插件本地化 文章手动发布时自动本地化 文章定时发布时自动本地化 针对已发布的文章…

BioTech - 药物晶型预测与剂型设计 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136441046 药物晶型预测与剂型设计是指利用计算机模拟和优化药物分子在固态形式下的结构、性质和稳定性&#xff0c;以及与制剂工艺和质…

一维数组、内存理解图--学习JavaEE的day9

day09 一、一维数组 理解&#xff1a; 一组数据的容器 应用场景&#xff1a; 存储多个数据的时候可以考虑使用数组 概念&#xff1a; ​ 1.数组是引用数据类型 ​ 2.数组中的数据&#xff0c;称之为元素 ​ 3.元素的都有编号&#xff0c;称之为下标/索引 ​ 4.下标从0开始 ​…

【MetaGPT】配置教程

MetaGPT配置教程&#xff08;使用智谱AI的GLM-4&#xff09; 文章目录 MetaGPT配置教程&#xff08;使用智谱AI的GLM-4&#xff09;零、为什么要学MetaGPT一、配置环境二、克隆代码仓库三、设置智谱AI配置四、 示例demo&#xff08;狼羊对决&#xff09;五、参考链接 零、为什么…

HTML和CSS (前端共三篇)【详解】

目录 一、前端开发介绍 二、HTML入门 三、HTML基础标签 四、CSS样式修饰 五、HTML表格标签 六、HTML表单标签 一、前端开发介绍 web应用有BS和CS架构两种&#xff0c;其中我们主要涉及的是BS架构。而BS架构里&#xff0c;B&#xff08;Browser浏览器&#xff09;是客户端的…

Sqli-labs靶场第21、22关详解[Sqli-labs-less-21、22]自动化注入-SQLmap工具注入|sqlmap跑base64加密

Sqli-labs-Less-21、22 由于21/22雷同&#xff0c;都是需要登录后&#xff0c;注入点通过Cookie值进行测试&#xff0c;值base64加密 修改注入数据 选项&#xff1a;--tamperbase64encode #自动化注入-SQLmap工具注入 SQLmap用户手册&#xff1a;文档介绍 - sqlmap 用户手册 由…

关于硅金属电阻器?

EAK金属硅电阻器类似于陶瓷复合电阻器&#xff0c;在脉冲负载方面具有优势&#xff0c;需要高峰值功率或高电压与低电感&#xff08;如预充电电路&#xff09;的组合。硅金属电阻器具有更高的连续额定温度&#xff0c;为 350C&#xff0c;而陶瓷电阻器为 250C。这种扩展的温度范…

【java】final、finally和finalize的区别

例题&#xff1a; package com.overload;public class ExceptionTest {public static void main(String[] args) {int result test();System.out.println(result); //100}public static int test(){int i 100;try {return i;} finally {i;}} }结果为&#xff1a;100 造成结果…

JUC并发编程 深入学习Java并发编程【上】

JUC并发编程&#xff0c;深入学习Java并发编程&#xff0c;与视频每一P对应&#xff0c;全系列6w字。 P1-5 为什么学特色预备知识 进程线程概念 进程&#xff1a; 一个程序被运行&#xff0c;从磁盘加载这个程序的代码到内存&#xff0c;就开起了一个进程。 进程可以视为程…

人工智能_大模型015_RAG量化检索增强002_AIGC大模型_本地知识库实时问答_私域和实时场景_量化检索增强---人工智能工作笔记0151

由于上一节我们提到的,关键词检索的局限性,现在我们引出向量检索, 关键词检索有语义上的缺陷,因为我们说法不一样,但是意思一样的话,那么,关键词如果在es库中没有,那么会导致,找不到答案的情况.所以我们引出向量检索,要求语义一样的词,去检索都能找到答案. 我们来说一下这个文…

突破编程_前端_JS编程实例(网站标题栏TAB组件)

1 开发目标 实现如下网站标题栏 TAB 组件&#xff1a; 在点击"页面2"选项卡后&#xff0c;TAB 组件会切换对应的面板&#xff1a; 2 详细需求 网站标题栏 TAB 组件该组件需根据客户端提供的参数创建&#xff0c;具备动态构建 TAB 区域、选项卡切换及自定义内容…

Django模型进阶(Mysql配置、模型管理,表关联、一对一、一对多,多对多)

模型进阶&#xff1a; Mysql配置&#xff1a; 1.安装mysql 2安装MySQL驱动&#xff0c;使⽤mysqlclient pip install mysqlclient pip install -i https://pypi.douban.com/simple mysqlclientLinux Ubuntu下需要先安装&#xff1a;apt install libmysqld-dev 再安装: apt…

[BJDCTF2020]EzPHP1 --不会编程的崽

有一说一&#xff0c;这题还是有难度的 base32解码url编码绕过$_SERVER换行符绕过preg_match相同参数&#xff0c;post请求覆盖get请求&#xff0c;绕过$_REQUESTphp伪协议利用sha1数组绕过create_function代码注入 Level 1 右键源码里又发现&#xff0c;拿去base32解码即可…

w30使用python调用shell脚本

使用python脚本去实现永恒之蓝漏洞攻击 实验环境 攻击工具&#xff1a;pythonmsfconsole 靶场&#xff1a;win7 和 kali实验目的 演示python脚本调用过程 实验步骤 1.写一个永恒之蓝的攻击脚本&#xff0c;定义为blue.rc use exploit/windows/smb/ms17_010_eternalblue …

Microsoft PyRIT能自动化完成AI红队的任务

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【算法集训】基础算法:枚举

一、基本理解 枚举的概念就是把满足题目条件的所有情况都列举出来&#xff0c;然后一一判定&#xff0c;找到最优解的过程。 枚举虽然看起来麻烦&#xff0c;但是有时效率上比排序高&#xff0c;也是一个不错的方法、 二、最值问题 1、两个数的最值问题 两个数的最小值&…

【Android】View事件体系基础

文章目录 坐标系View滑动layout方法offserLeftAndRight() 和 offsetTopAndBottom()LayoutParams(布局参数)View动画scrollTo/scrollBy 解析Activity的构成 坐标系 分为Android坐标系和View坐标系 可以用 getWidth() 和 getHeight() 获取View自身的宽度和高度 对于ViewgetX() …

求Sn=a+aa+aaa+aaaa+aaaaa的前n项之和

求Snaaaaaaaaaaaaaaa的前5项之和&#xff0c;其中a是一个数字&#xff0c; 例如&#xff1a;222222222222222 int main() {int a;scanf("%d", &a);int n;scanf("%d", &n);int sum 0;int tmp 0;for (int i 0; i < n; i){tmp tmp * 10 a;sum…

bxCAN总线的工作模式和测试模式(STM32F4xx)

概述 本文主要介绍STM32F4XX的bxCAN知识&#xff0c;包括bxCAN的概念&#xff0c;各种工作模式下特性&#xff0c;如何配置各类工作模式等内容&#xff0c;还介绍了bxCAN的测试模式&#xff0c;bxCAN测试模式有3种工作类型&#xff0c;每种类型有什么特性&#xff0c;以及如何配…