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("加载动画 第8季");
    QGridLayout * mainLayout = new QGridLayout;

    auto* anim1= new TextInBouncingBox("正在加载");
    mainLayout->addWidget(anim1,0,0);

    auto* anim2 = new TextInBouncingBox("正在加载中");
    anim2->setBoxColor("slateblue");
    anim2->setTextColor("white");
    mainLayout->addWidget(anim2,0,1);

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

    w.setLayout(mainLayout);
    w.show();
    anim1->start();
    anim2->start();
    anim3->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 TextInBouncingBox:public LoadingAnimBase{//显示装在上下跳动的盒子里的字符
public:
    TextInBouncingBox(const QString & str,QWidget* parent = nullptr);
    void setTextColor(const QColor& color);
    void setBoxColor(const QColor& color);
protected:
    void paintEvent(QPaintEvent*);
private:
    QString mText;
    QColor mTextColor;
    QColor mBoxColor;
};
class ExpandingScroll:public LoadingAnimBase{//一个圆环转动两圈之后像卷轴一样展示"正在加载"
public:
    ExpandingScroll(QWidget* parent = nullptr);
protected:
    void paintEvent(QPaintEvent*);
};
#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();
}
TextInBouncingBox::TextInBouncingBox(const QString& str,QWidget* parent ):LoadingAnimBase (parent),
    mText(str),mBoxColor("darkslategray"),mTextColor("yellow"){
    setFont(QFont("Microsoft YaHei",16,2));
}
void TextInBouncingBox::setTextColor(const QColor& color){
    if(mTextColor != color){
        mTextColor = color;
        update();
    }
}
void TextInBouncingBox::setBoxColor(const QColor& color){
    if(mBoxColor != color){
        mBoxColor = color;
        update();
    }
}

void TextInBouncingBox::paintEvent(QPaintEvent*){
    const int len = mText.size();
    if(len <= 0) return;
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QFontMetrics fm(font());
    const int txtH = fm.height();
    const int rectH = txtH + 4;
    const int rectW = fm.horizontalAdvance("w")+4;
    const qreal x = width();
    const qreal y = height();
    painter.translate(0.1*x,0.6*y);
    painter.setBrush(QBrush(mBoxColor));

    const qreal amplitude = rectH*0.3;
    const qreal offset = M_PI / len / 2;
    for(int i = 0;i < len;++i){
        QRectF rct( i*rectW,-rectH - amplitude*qSin(-2*M_PI / 360 * mAngle + offset*i) ,rectW,rectH);
        painter.setPen(Qt::NoPen);
        painter.drawRect(rct);  //画一个小盒子
        painter.setPen(mTextColor);
        painter.drawText(rct,Qt::AlignCenter,QString(mText[i])); //画一个字符
    }
}

ExpandingScroll::ExpandingScroll(QWidget* parent):LoadingAnimBase (parent){
    setFont(QFont("Microsoft YaHei",16,2));
    mAnim.setDuration(4000);
}

void ExpandingScroll::paintEvent(QPaintEvent*){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    qreal x = width();
    qreal y = height();
    painter.translate(x/2,y/2);
    painter.setBrush(Qt::NoBrush);
    QPen pen("black");
    static const qreal penWidth = 4;
    pen.setWidthF(penWidth);
    painter.setPen(pen);
    x -= 4;
    y -= 4;
    const auto ang = mAngle;

    const int arr[9] = {20,30,60,90,150,180,210,275,345};//9个时间节点,分割下面10个分支

    if(ang < arr[0]){//中间的竖线转变为半圆弧线
        const qreal h = 0.25*x;
        painter.drawLine(0,h/2 - ang/arr[0] * h,0,-h/2);
        painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),180*16,-180*16*ang/arr[0]);
    }
    else if(ang < arr[1]){//半圆弧线转变为四分之一圆弧和右侧的小竖线
        const qreal h = 0.25*x;
        const qreal ratio = (ang-arr[0])/(arr[1] - arr[0]);
        qreal start = 180 - 90*ratio;

        painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),start*16,-start*16);
        painter.drawLine(x/2,-h/2,x/2,-h/2+h/2*ratio);
    }
    else if(ang < arr[2]){//剩下的上方的四分之一圆弧转为大的下方的八分之一圆弧
        const qreal h = 0.25*x;
        const qreal ratio = (ang - arr[1]) / (arr[2] - arr[1]);
        qreal start = 90 - 90 * ratio;
        painter.drawArc(QRectF(0,-1.5*h,2*h,2*h),start*16,-start*16);
        painter.drawLine(x/2,-h/2,x/2,0);
        painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-45*16*ratio);
    }
    else if(ang < arr[3]){//小竖线转为下方的大的八分之一圆弧
        const qreal h = x/8;
        qreal ratio = (ang-arr[2]) / (arr[3] - arr[2]);
        painter.drawLine(x/2,-h*(1-ratio),x/2,0);
        painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-(45+45*ratio)*16);
    }
    else if(ang < arr[4]){//大圆弧转两圈
        qreal ratio = (ang - arr[3]) / (arr[4] - arr[3]);
        painter.rotate(720*ratio);
        painter.drawArc(QRectF(-x/2,-y/2,x,y),0,-90*16);
    }
    else if(ang < arr[5]){//大圆弧转为竖线
        qreal ratio = (ang-arr[4]) / (arr[5] - arr[4]);
        painter.drawArc(QRectF(-x/2,-y/2,x,y),-90*ratio*16,-90*(1-ratio)*16);
        painter.drawLine(0,y/2,0,y/2 - 0.625*ratio*y);
    }
    else if(ang < arr[6]){//竖线缩小一下
        qreal ratio = (ang - arr[5]) / (arr[6] - arr[5]);
        painter.drawLine(0,y/2 - 0.375*y*ratio,0,-0.125*y);
    }
    else if(ang < arr[7]){//展开卷轴
        qreal ratio = (ang - arr[6]) / (arr[7] - arr[6]);
        QPainterPath pp;
        pp.addRect(QRectF(-0.375*x*ratio,-0.125*y,0.75*x*ratio,y/4).adjusted(
                       penWidth/-2,penWidth/-2,penWidth/2,penWidth/2));
        painter.setClipPath(pp);
        const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);

        painter.setBrush(QBrush("burlywood"));
        painter.drawRoundedRect(rct,4,4);
        painter.drawText(rct,Qt::AlignCenter,"正在加载");
    }
    else if(ang < arr[8]){//展示一小段时间
        const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);
        painter.setBrush(QBrush("burlywood"));
        painter.drawRoundedRect(rct,4,4);
        painter.drawText(rct,Qt::AlignCenter,"正在加载");
    }
    else{//收起卷轴
        qreal ratio = (ang - arr[8])/(360 - arr[8]);
        QPainterPath pp;
        pp.addRect(QRectF(-0.375*x* (1-ratio),-0.125*y,0.75*x*(1-ratio),y/4).adjusted(
                       penWidth/-2,penWidth/-2,penWidth/2,penWidth/2));
        painter.setClipPath(pp);
        const auto rct = QRectF(-0.375*x,-0.125*y,0.75*x,y/4);
        painter.setBrush(QBrush("burlywood"));
        painter.drawRoundedRect(rct,4,4);
        painter.drawText(rct,Qt::AlignCenter,"正在加载");
    }
}
相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript