QPainter绘制一个简单的等待动画

使用场景

在我们软件上有时候需要做一些耗时操作,这时界面上应该有明确的的显示表明耗时操作正在进行中,而Qt中并没有提供此类控件,那就自己造轮子吧。

效果展示

在这里插入图片描述

示例代码

1、头文件

#ifndef WAITANIMATION_H
#define WAITANIMATION_H

#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>

class WaitAnimation : public QWidget
{
    Q_OBJECT
public:
    WaitAnimation(QWidget *parent = nullptr);
    ~WaitAnimation();
    
    QColor foreColor() const;
    void setForeColor(const QColor &newForeColor);

    quint32 interval() const;
    void setInterval(quint32 newInterval);

signals:
    void foreColorChanged();
    void intervalChanged();

protected:
    void paintEvent(QPaintEvent*) override;
    void timerEvent(QTimerEvent*) override;
    void drawPoints(QPainter*);
private:
    QColor mForeColor;//前景色
    Q_PROPERTY(QColor foreColor READ foreColor WRITE setForeColor NOTIFY foreColorChanged FINAL)
    quint32 mInterval;//绘制间隔,毫秒
    Q_PROPERTY(quint32 interval READ interval WRITE setInterval NOTIFY intervalChanged FINAL)
    quint32 startIndex;//每次绘制的起始角度索引
    const quint32 pointCounts = 16;//画n个圆点,每个圆之间的角度偏移为360/n度
};
#endif // WAITANIMATION_H

2、cpp文件

#include "waitanimation.h"

WaitAnimation::WaitAnimation(QWidget *parent)
    : QWidget(parent),
    mForeColor(QColor(255,102,102,255)),
    mInterval(50),
    startIndex(0)
{
    //无边框、置顶
    setWindowFlags(this->windowFlags()|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
    //设置窗口背景透明
    setAttribute(Qt::WA_TranslucentBackground);
    startTimer(mInterval);
}

WaitAnimation::~WaitAnimation() {}

void WaitAnimation::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setPen(Qt::NoPen);
    p.setRenderHint(QPainter::Antialiasing);
    drawPoints(&p);
}

void WaitAnimation::timerEvent(QTimerEvent *)
{
    startIndex %= pointCounts;
    this->update();
    startIndex++;
}

void WaitAnimation::drawPoints(QPainter *p)
{
    p->save();

    quint32 curWidth = this->size().width();
    quint32 curHeight = this->size().height();
    quint32 refSize = qMin(curWidth, curHeight);
    quint32 radius = refSize/2;
    quint32 pointDiameter = refSize/12;//画圆的直径,相对窗口的大小
    //坐标原点移动到中间
    p->translate(refSize/2, refSize/2);
    //第一个圆相对坐标原点的偏转角度
    p->rotate(startIndex * 360/pointCounts);
    for(quint32 index = 0; index < pointCounts; index++)
    {
        p->setBrush(QColor(mForeColor.red(),mForeColor.green(),mForeColor.blue(),index*255/pointCounts));
        p->rotate(360/pointCounts);//每画一个圆都偏转固定的角度
        p->drawEllipse(radius - pointDiameter, 0 - pointDiameter/2, pointDiameter, pointDiameter);
    }
    p->restore();
}

QColor WaitAnimation::foreColor() const
{
    return mForeColor;
}

void WaitAnimation::setForeColor(const QColor &newForeColor)
{
    if (mForeColor == newForeColor)
        return;
    mForeColor = newForeColor;
    emit foreColorChanged();
}

quint32 WaitAnimation::interval() const
{
    return mInterval;
}

void WaitAnimation::setInterval(quint32 newInterval)
{
    if (mInterval == newInterval)
        return;
    mInterval = newInterval;
    emit intervalChanged();
}

3、使用示例

#include <QApplication>
#include "waitanimation.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    WaitAnimation w;
    w.setGeometry(800,800,200,210);
    w.show();
    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值