Qt 简约又简单的加载动画 第七季 音量柱风格

今天和大家分享两个音量柱风格的加载动画,这次的加载动画的最大特点就是简单,只有几行代码. 效果如下:

一共三个文件,可以直接编译运行

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

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

    auto* anim2 = new MagnitudeMeter;
    mainLayout->addWidget(anim2,0,1);
    anim2->setColor("lightblue");

    auto* anim3 = new MagnitudeMeter;
    mainLayout->addWidget(anim3,0,2);
    anim3->setColor("slateblue");

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

    auto* anim5 = new ThreeColumn;
    mainLayout->addWidget(anim5,1,1);
    anim5->setColor("lightblue");

    auto* anim6 = new ThreeColumn;
    mainLayout->addWidget(anim6,1,2);
    anim6->setColor("slateblue");

    w.setLayout(mainLayout);
    w.show();
    anim1->start();anim2->start();anim3->start();anim4->start();anim5->start();anim6->start();
    return a.exec();
}
cpp 复制代码
//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 MagnitudeMeter:public LoadingAnimBase{//一个类似音量检测器的动画,有一排小柱子,它们的高度随时变化
public:
    MagnitudeMeter(QWidget* parent = nullptr);
    void setColor(const QColor& color);
protected:
    void paintEvent(QPaintEvent*);
private:
    QColor mColor;
};
class ThreeColumn:public LoadingAnimBase{//上一个的简化版,三个循环变化高度的小柱子
public:
    ThreeColumn(QWidget* parent = nullptr);
    void setColor(const QColor& color);
protected:
    void paintEvent(QPaintEvent*);
private:
    QColor mColor;
};
#endif
cpp 复制代码
//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();
}

MagnitudeMeter::MagnitudeMeter(QWidget* parent):LoadingAnimBase(parent),mColor("cadetblue"){
    mAnim.setDuration(8000);
}
void MagnitudeMeter::setColor(const QColor& color){
    if(mColor != color){
        mColor = color;
        update();
    }
}

void MagnitudeMeter::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush(mColor));

    const qreal x = width();
    const qreal y = height();

    static const int amount = 8;//8个小柱子
    static const int gap = 2;//小柱子之间的间距
    const qreal w = (0.667*x - (amount-1)*gap) / amount;

    painter.translate(x/6,0.667*y);
    static QList<qreal> offsetList;
    static QList<qreal> factorList;
    if(offsetList.size() <= 0){
        QRandomGenerator g;
        for(int i = 0;i < amount;++i) offsetList.push_back(g.bounded(1.0) * 2*M_PI);
        for(int i = 0;i < amount;++i) factorList.push_back(g.bounded(4) + 1);//周期不一样
    }

    for(int i = 0;i < amount;++i){
        const int maxh = y/3;
        const int h = (1+qSin((2*M_PI/360 * mAngle * factorList[i]) + offsetList[i]))/2 * 0.8*maxh+0.2*maxh;
        painter.drawRect(i*(gap + w),-h,w,h);
    }
}
ThreeColumn::ThreeColumn(QWidget* parent):LoadingAnimBase (parent),mColor("cadetblue"){}
void ThreeColumn::setColor(const QColor& color){
    if(mColor != color){
        mColor = color;
        update();
    }
}
void ThreeColumn::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush(mColor));
    const qreal x = width();
    const qreal y = height();
    painter.translate(x/2,y/2);
    static const int w = 8;
    static const int h = 16;
    static const int gap = 4;
    qreal h1 = h/2+h/2*qSin(-2*M_PI/360*mAngle);
    qreal h2 = h/2+h/2*qSin(-2*M_PI/360*mAngle + M_PI*2/3);
    qreal h3 = h/2+h/2*qSin(-2*M_PI/360*mAngle + M_PI*4/3);
    qreal yList[3] = {-h1,-h2,-h3};
    qreal xList[3] = {-1.5*w-gap,-0.5*w,0.5*w+gap};
    for(int i = 0;i < 3;++i){
        painter.drawRect(QRectF(xList[i],yList[i],w,-2*yList[i]));
    }
}
相关推荐
isyangli_blog11 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081111 小时前
FastAPI APIRouter
开发语言·python
Benszen11 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆11 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木11 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充11 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~11 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball61612 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草12 小时前
反射、Tomcat执行
java·开发语言
雪的季节13 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt