qt实现语音播放脉冲动效

语音播放脉冲运行效果:

代码:

#ifndef MYVOICEQUOTELOADINGWIDGET_H
#define MYVOICEQUOTELOADINGWIDGET_H

#include <QWidget>
// 语音播放动态icon
//     1、icon尺寸:
//     16*16
//     2、柱子尺寸:
//     h最长=12,最短=3;
// w=2;
//     间距=3;
//     3、颜色:FFFFFF
//     4、圆角:1
// 从左到右依次阶梯变短
class QPropertyAnimation;
class MyVoiceQuoteLoadingWidget : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(int status READ status WRITE setStatus)
public:
    explicit MyVoiceQuoteLoadingWidget(QWidget* parent = nullptr);
    ~MyVoiceQuoteLoadingWidget(){}
    void start();
    void stop();

public:
    int status() const;
    void setStatus(int newStatus);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    int mStatus { -100000 };
    QPropertyAnimation *mAnimation {nullptr};
    void init();
};

#endif   // MYVOICEQUOTELOADINGWIDGET_H
#include "myvoicequoteloadingwidget.h"

#include <QPropertyAnimation>
#define MIN_VALUE 0
#define MAX_VALUE 3000
#define BASE_VALUE 1000
MyVoiceQuoteLoadingWidget::MyVoiceQuoteLoadingWidget(QWidget* parent) : QWidget { parent }
{
    init();
}

void MyVoiceQuoteLoadingWidget::start()
{
    if (mAnimation->state() != QAbstractAnimation::Running) {
        mAnimation->start();
    }
}

void MyVoiceQuoteLoadingWidget::stop()
{
    mAnimation->stop();
    setStatus(-2*MAX_VALUE);
}

void MyVoiceQuoteLoadingWidget::init()
{
    setFixedSize(16, 16);
    mAnimation = new QPropertyAnimation(this, "status", this);
    mAnimation->setDuration(800);
    mAnimation->setStartValue(-MAX_VALUE);
    mAnimation->setEndValue(MAX_VALUE);
    mAnimation->setLoopCount(-1);
}

int MyVoiceQuoteLoadingWidget::status() const
{
    return mStatus;
}

void MyVoiceQuoteLoadingWidget::setStatus(int newStatus)
{
    if (newStatus == mStatus) return;
    mStatus = newStatus;
    update();
}

// 播放动态icon
//     1、icon尺寸:
//     16*16
//     2、柱子尺寸:
//     h最长=12,最短=3;
// w=2;
//     间距=3;
//     3、颜色:FFFFFF
//     4、圆角:1
// 从左到右依次阶梯变短
void MyVoiceQuoteLoadingWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    //const qreal spacing = 3;
    if (height() < 12 || width() < 12) {
        return;
    }
    const qreal barW = 2;
    const qreal maxBarHeight = 12;
    const qreal midBarHeight = 7.5;
    const qreal minBarHeight = 3;
    const qreal padding = 2.0;
    qreal h = height();
    qreal w = width();
    qreal x0 = padding;
    qreal x1 = w/2.0 - 0.5;
    qreal x2 = w - padding - barW/2.0;
    QColor cor = Qt::white;
    QPainter p(this);
    p.setRenderHints(QPainter::Antialiasing);
    p.setPen(QPen(cor, barW, Qt::SolidLine, Qt::RoundCap));
    p.setBrush(Qt::NoBrush);
    qreal factor = 1.0 - (mStatus % BASE_VALUE) / qreal(BASE_VALUE);
    if (mStatus >= 0) {
        factor = 1.0 - (mStatus % BASE_VALUE) / qreal(BASE_VALUE);
    } else {
        factor = 1.0 - (qAbs(mStatus) % BASE_VALUE) / qreal(BASE_VALUE);
    }
    qreal barH = 0;
    qreal vOffset = 0;
    int status = qAbs(mStatus);
    if (BASE_VALUE*2 < status && status <= MAX_VALUE) {
        // 第一根柱子
        barH = midBarHeight - (maxBarHeight - minBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x0, vOffset), QPointF(x0, vOffset + barH));
        // 第二根柱子
        barH = midBarHeight + (maxBarHeight - midBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x1, vOffset), QPointF(x1, vOffset + barH));
        // 第三根柱子
        barH = minBarHeight;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x2, vOffset), QPointF(x2, vOffset + barH));
    } else if (BASE_VALUE < status && status <= BASE_VALUE*2) {
        // 第二根柱子
        barH = maxBarHeight - (maxBarHeight - minBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x1, vOffset), QPointF(x1, vOffset + barH));
        // 第三根柱子
        barH = midBarHeight + (maxBarHeight - midBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x2, vOffset), QPointF(x2, vOffset + barH));
        // 第一根柱子
        barH = minBarHeight;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x0, vOffset), QPointF(x0, vOffset + barH));
    } else if (MIN_VALUE <= status && status <= BASE_VALUE) {
        // 第三根柱子
        barH = maxBarHeight - (maxBarHeight - minBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x2, vOffset), QPointF(x2, vOffset + barH));
        // 第一根柱子
        barH = midBarHeight + (maxBarHeight - midBarHeight)*factor;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x0, vOffset), QPointF(x0, vOffset + barH));
        // 第二根柱子
        barH = minBarHeight;
        vOffset = (h - barH)/2.0;
        p.drawLine(QPointF(x1, vOffset), QPointF(x1, vOffset + barH));
    } else {
        p.drawLine(QPointF(x0, (h - midBarHeight)/2.0), QPointF(x0, (h - midBarHeight)/2.0 + midBarHeight));
        p.drawLine(QPointF(x1, (h - maxBarHeight)/2.0), QPointF(x1, (h - maxBarHeight)/2.0 + maxBarHeight));
        p.drawLine(QPointF(x2, (h - midBarHeight)/2.0), QPointF(x2, (h - midBarHeight)/2.0 + midBarHeight));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值