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]));
    }
}
相关推荐
宅小海7 分钟前
scala String
大数据·开发语言·scala
qq_3273427310 分钟前
Java实现离线身份证号码OCR识别
java·开发语言
锅包肉的九珍11 分钟前
Scala的Array数组
开发语言·后端·scala
心仪悦悦14 分钟前
Scala的Array(2)
开发语言·后端·scala
yqcoder37 分钟前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
baivfhpwxf20231 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
许嵩661 小时前
IC脚本之perl
开发语言·perl
长亭外的少年1 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
直裾1 小时前
Scala全文单词统计
开发语言·c#·scala
心仪悦悦1 小时前
Scala中的集合复习(1)
开发语言·后端·scala