Qt 简约美观的动画 摆钟风格 第十季

😊 今天给大家分享一个摆钟风格的加载动画 😊
效果如下:
在这里插入图片描述
最近工作忙起来了 , 后续再分享其他有趣的加载动画吧.
一共三个文件 , 可以直接编译运行

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

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

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

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

    auto* anim4 = new StickCircle;
    anim4->setStickColor("lime");
    anim4->setStickWidth(16);
    anim4->setStickLength(32);
    mainLayout->addWidget(anim4,1,0);

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

    auto* anim6 = new AmpereMeter;
    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 StickCircle:public LoadingAnimBase
{
    Q_OBJECT
public:
    explicit StickCircle(QWidget* parent = nullptr);
    void setStickLength(qreal len);
    void setStickWidth(qreal len);
    void setStickColor(const QColor& color);
protected:
    void paintEvent(QPaintEvent *event);
private:
    qreal mStickLen;
    qreal mStickWidth;
    QColor mStickColor;
};
class ThreeMovingZoomingBalls:public LoadingAnimBase{//三个一边移动一边缩放的小球
public:
    ThreeMovingZoomingBalls(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class FourRotatingFireBall:public LoadingAnimBase{//四个旋转的火球,说他是火球是因为快速转动的时候它有残影,看上去像弧线
public:
    FourRotatingFireBall(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class CookieMonster:public LoadingAnimBase{//一个不停吃饼干的怪兽
public:
    CookieMonster(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class PendulumClock:public LoadingAnimBase{//吊钟钟摆
public:
    PendulumClock(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
class AmpereMeter :public LoadingAnimBase{//电流表的指针
public:
    AmpereMeter(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();
}
StickCircle::StickCircle(QWidget *parent) : LoadingAnimBase(parent),
    mStickLen(-1),mStickWidth(10),mStickColor("black"){}
void StickCircle::setStickLength(qreal len){
    if(len > 0 && len != mStickLen){
        mStickLen = len;
        update();
    }
}
void StickCircle::setStickWidth(qreal len){
    if(len > 0 && len != mStickWidth){
        mStickWidth = len;
        update();
    }
}
void StickCircle::setStickColor(const QColor& color){
    if(color.isValid() && mStickColor != color){
        mStickColor = color;
        update();
    }
}
void StickCircle::paintEvent(QPaintEvent *event){
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);
    int x = width();
    int y = height();
    qreal ang = mAngle;

    painter.setPen(Qt::NoPen);
    painter.translate(x/2,y/2);
    QColor lightColor = mStickColor;
    lightColor.setAlphaF(0.1);
    const int stickw = mStickWidth;//小棍子的宽度
    qreal stickl = x / 4;//小棍子的长度
    if(mStickLen > 0) stickl = mStickLen;

    QColor highlight = mStickColor;
    const int startIdx = ang / 30;//开头的深色小棍子的索引号
    const int arr[14] = {0,1,2,3,4,5,6,7,8,9,10,11,0,1};
    QList<int> hightlightList{arr[startIdx],arr[startIdx+1],arr[startIdx+2]};
    QList<qreal> alphaList{0.5,0.75,0.99};//三根深色的小棍子的透明度

    for(int i = 0;i < 12;++i){
        if(hightlightList.contains(i)){
            auto hc = highlight;
            hc.setAlphaF(alphaList[0]);
            painter.setBrush(QBrush(hc));
            alphaList.pop_front();
        }
        else {
            painter.setBrush(QBrush(lightColor));
        }
        painter.drawRoundedRect(QRectF(-stickw/2,0.375*y -stickl/2-1,stickw,stickl),stickw/2,stickw/2);
        auto transform = painter.transform();
        transform.rotate(30);
        painter.setTransform(transform);
    }
}
ThreeMovingZoomingBalls::ThreeMovingZoomingBalls(QWidget* parent):LoadingAnimBase(parent){}
void ThreeMovingZoomingBalls::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush("cadetblue"));
    qreal x = width();
    qreal y = height();
    painter.translate(0,y/2);
    const qreal delta = 0.08*x;
    const qreal minr = 0.02*x;
    for(int i = 0;i < 5;++i){
        qreal ang = mAngle + 90*i;
        qreal posx = ang/360*x;
        if(posx > x) posx -= x;
        qreal r = minr + delta * qSin(M_PI / x * posx);
        painter.drawEllipse(QPointF(posx,0),r,r);
    }
}
FourRotatingFireBall::FourRotatingFireBall(QWidget* parent){}
void FourRotatingFireBall::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    pen.setWidth(12);
    painter.setPen(pen);
    painter.setBrush(Qt::NoBrush);
    const qreal x = width();
    const qreal y = height();
    const qreal r = 0.4*y;
    const qreal maxArc = 30;

    for(int i = 0;i <4;++i){
        painter.resetTransform();
        painter.translate(x/2,y/2);
        painter.rotate(90*i);
        if(i % 2 == 0){
            pen.setColor("lightblue");
            painter.setPen(pen);
        }
        else{
            pen.setColor("lightpink");
            painter.setPen(pen);
        }
        if(mAngle < 30){ //启动火球,画出弧线
            qreal ratio = mAngle / 30;
            painter.drawArc(QRectF(-r,-r,2*r,2*r),16*90,16*-ratio*maxArc);
        }
        else if(mAngle < 330){//转动两圈
            qreal ratio = (mAngle - 30) / 300;
            painter.rotate((720-maxArc)*ratio);
            painter.drawArc(QRectF(-r,-r,2*r,2*r),16*90,16*-maxArc);
        }
        else{//收起弧线
            qreal ratio = (mAngle - 330) / 30;
            painter.drawArc(QRectF(-r,-r,2*r,2*r),16*90,16*(1-ratio)*maxArc);
        }
    }
}
CookieMonster::CookieMonster(QWidget* parent):LoadingAnimBase(parent){}

void CookieMonster::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    const qreal r = 0.2*x;
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush("royalblue"));
    painter.translate(4,y/2);
    qreal startAngle = 22.5 + 22.5*qSin(M_PI / 90 * mAngle + M_PI/2);
    qreal span = 360 - 2*startAngle;
    painter.drawPie(QRectF(0,-r,2*r,2*r),startAngle*16,span*16);
    painter.setBrush(QBrush("white"));
    painter.drawEllipse(QPointF(r*0.8,-r/2),4,4);

    //画移动的小饼干
    painter.setBrush(QBrush("lightgreen"));
    painter.resetTransform();
    painter.translate(x,y/2);
    qreal ratio = mAngle / 360;
    for(int i = 0;i <3;++i){
        ratio += 0.333;
        if(ratio > 1) ratio -= 1;
        painter.drawEllipse(QPointF( -(x-2*r)*ratio,0 ) , 8,8);
    }
}
PendulumClock::PendulumClock(QWidget* parent):LoadingAnimBase(parent){}

void PendulumClock::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/8);
    QPen pen("silver");
    pen.setWidth(4);
    painter.setPen(pen);
    painter.rotate(30*qSin(M_PI/180*mAngle));
    painter.setBrush(QBrush("silver"));
    painter.drawLine(0,0,0,0.6*y);
    painter.translate(0,0.6*y);
    painter.drawEllipse(QPointF(0,0),16,16);
}
AmpereMeter::AmpereMeter(QWidget* parent):LoadingAnimBase(parent){}

void AmpereMeter::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y*0.6);
    QPen pen("dimgray");
    pen.setWidth(4);
    painter.setPen(pen);
    painter.setBrush(Qt::NoBrush);
    const qreal r = x*0.4;
    //step1 先画一个表框
    painter.drawArc(QRectF(-r,-r,2*r,2*r),0,180*16);
    //step2 再画半圈刻度
    qreal gap = 180 / 14.0;
    painter.rotate(-90);
    for(int i = 1;i <= 13;++i){
        painter.rotate(gap);
        painter.drawLine(0,-r + 6,0,-r + 8);
    }
    //step3 画指针
    painter.resetTransform();
    painter.translate(x/2,y*0.6);
    painter.rotate(80*qSin(M_PI/180*mAngle));
    painter.drawLine(0,0,0,-r*0.7);

}

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

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

相关文章

山西电力市场日前价格预测【2024-02-24】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-24&#xff09;山西电力市场全天平均日前电价为562.29元/MWh。其中&#xff0c;最高日前电价为1026.21元/MWh&#xff0c;预计出现在18:30。最低日前电价为337.39元/MWh&#xff0c;预计…

[LeetBook]【学习日记】寻找和为指定数字的连续数字

题目 文件组合 待传输文件被切分成多个部分&#xff0c;按照原排列顺序&#xff0c;每部分文件编号均为一个 正整数&#xff08;至少含有两个文件&#xff09;。传输要求为&#xff1a;连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组…

【音视频开发】使用ffmpeg实现多个视频合成一个视频(按宫格视图)

先上结果 环境 硬件&#xff1a;通用PC 系统&#xff1a;Windows 测试有效 软件&#xff1a;ffmpeg 解决 0、命令 ffmpeg.exe -i input1.mp4 -i input2.mp4 -i input3.mp4 -i input4.mp4 -filter_complex "[0:v]scaleiw/2:ih/2,pad2*iw:2*ih[a]; [1:v]scaleiw/2:ih/2…

ArcGIS学习(九)选址分析

ArcGIS学习(九)选址分析 本任务给大家带来的案例是租房选址分析。选址分析是我们平时经常接触到的分析场景。概括起来说,选址分析就是根据选址条件来确定哪些区域满足我们的选址要求。首先,先来看看我们这个案例的场景和基础数据。我们以某个城市某一租客的租房选址为例。…

深入理解Docker

文章目录 1 Docker理论1.1 背景知识1.2 是什么1.3 Docker基本三要素1.4 镜像原理1.5 安装教程 2 Docker常用命令2.0 防火墙相关命令2.1 镜像命令2.2 容器命令2.3 进阶命令 3. 实战之Docker部署springboot项目步骤一&#xff1a;Springboot项目配置1.1 添加docker的maven依赖1.2…

vue项目中使用antvX6新手教程,附demo案例讲解(可拖拽流程图、网络拓扑图)

前言&#xff1a; 之前分别做了vue2和vue3项目里的网络拓扑图功能&#xff0c;发现对antv X6的讲解博客比较少&#xff0c;最近终于得闲码一篇了&#xff01; 需求&#xff1a; 用户可以自己拖拽节点&#xff0c;节点之间可以随意连线&#xff0c;保存拓扑图数据后传给后端&…

力扣61:旋转链表

题目 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2输出&#xff1a;[4,5,1,2,3] 示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4输出&#xff1a;…

【硬件相关】Mellanox网络配置及参数优化

文章目录 一、前言1、硬件配置2、网卡信息 二、驱动安装1、驱动介绍2、软件架构2.1、mlx4 VPI Driver2.2、mlx5 Driver 3、驱动安装3.1、常规安装3.2、驱动编译方法一方法二 4、RDMA配置 三、交换机配置四、mlnx-tools管理工具1、软件安装2、软件使用ibdev2netdeva、说明b、用法…

【MySQL系列】在 MacOS 上安装 MySQL

在 MacOS 上有两种方式安装 MySQL 服务器&#xff1a;通过 brew 安装和通过安装包安装。 文章目录 1、通过 brew 安装 MySQL1.1、安装 MySQL1.2、启动 MySQL 服务器1.3、配置 MySQL 服务器1.4、MySQL 服务器管理命令 2、通过安装包安装 MySQL2.1、下载安装包2.2、安装 MySQL2.3…

Vue3:使用 Composition API 不需要 Pinia

在 Vue.js 开发的动态环境中&#xff0c;在单个组件中处理复杂的业务逻辑可能会导致笨重的文件和维护噩梦。虽然 Pinia 提供集中式状态管理&#xff0c;但仅依赖它来处理复杂的业务逻辑可能会导致代码混乱。本文探讨了使用 Composition API 的替代方法&#xff0c;说明开发人员…

mysql学习笔记5——对表的修改操作

对表的列进行操作 对表可以进行创建create与删除drop&#xff0c;同时可以对表进行修改alter 修改字段 添加字段 删除具体的某一列 添加列时可以指定添加位置 对表的数据进行操作 select查询操作可以指定查询条件 删除具体数据&#xff08;而非删除表中某一列某一行&#xf…

【重要公告】对BSV警报系统AS的释义

​​发表时间&#xff1a;2024年2月15日 由BSV区块链协会开发并管理的BSV警报系统&#xff08;Alert System&#xff0c;以下简称“AS”&#xff09;是BSV网络的重要组件。它是一个复杂的系统&#xff0c;主要职能是在BSV区块链网络内发布信息。这些信息通常与网络访问规则NAR相…

ChatGPT论文指南|ChatGPT如何助力论文中的数据分析!【建议收藏】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 公众号原文▼▼▼▼&#xff1a; ChatGPT论文指南|ChatGPT如何助力论文中的数据分析&#xff01;【建议收藏】 小编在之前的论文写作流程中&#xff0c;介绍了大量论文文字工作&#xff…

VUE引入高德地图区域划分district结果为空(Cannot read properties of undefined (reading ‘0‘))

1.错误 Uncaught TypeError: Cannot read properties of undefined (reading 0) 通过debugger去看status、result结果status为no_data,而result为空 2.原因 大概率就是key过期了或者配置错了 3.正确配置 </script> <!-- 注意&#xff1a;导入密钥要在接口上面&…

2024.3.4 作业

1、流式域套接字 1>tcp服务端实现 #include<myhead.h> int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_UNIX, SOCK_STREAM, 0);if(sfd -1){perror("socket error");return -1;}//2、判断套接字文件是否存在&#xff0c;如果…

史上最细,企业性能测试步骤详细,测试老鸟带你一篇打通!

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、性能测试流程 …

总线要点笔记

1. AXI/AHB/APB差异 AMBA (Advanced Microcontroller Bus Architecture) 高级处理器总线架构 AHB (Advanced High-performance Bus) 高级高性能总线 ASB (Advanced System Bus) 高级系统总线 APB (Advanced Peripheral Bus) 高级外围总线 AXI (Advanced eXtensible Interface) …

【洛谷 P8682】[蓝桥杯 2019 省 B] 等差数列 题解(数学+排序+差分)

[蓝桥杯 2019 省 B] 等差数列 题目描述 数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列&#xff0c;只记得其中 N N N 个整数。 现在给出这 N N N 个整数&#xff0c;小明想知道包含这 N N N 个整数的最短的等差数列有几项&#xff1f; 输…

探究大语言模型如何使用长上下文

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文链接&#xff1a;https://doi.org/10.1162/tacl_a_00638 论文标题&#xff1a;Lost in the Middle: How Language Models Use Long Contexts 论文发表期刊&#xff1a;Transactions of the Assoc…

【Apple Vision Pro应用】Cinephile——Cinema Mode for Local Video(苹果眼睛视频播放器)

Cinephile 为您提供了一个完全无干扰、无限制的无限空间&#xff0c;让您尽享视频的精彩。它创造了一种身临其境的环境&#xff0c;您可以在能够想象到的最大屏幕上&#xff0c;从任何角度或位置观看内容。 您可以根据个人喜好自由调整视频的大小和位置。添加视频中的环境光&am…