在Qt中,如果你想通过传统的Widget方式实现波形扩散效果,可以使用以下步骤:
创建自定义Widget:继承自QWidget,并重写paintEvent方法来绘制波形。
绘制波形:在paintEvent中使用QPainter来绘制波形。
实现扩散动画:使用QTimer和自定义的变量来控制波形的变化,并触发重绘。
更新视图:在动画过程中,通过定时器触发重绘来更新波形的显示。
代码如下
#include "qtantanscanning.h"
#include <QTimer>
#include <QPainter>
#include <QVector>
#include <QPair>
#include <QDebug>
#include <QRectF>
#include <QMouseEvent>
#include <QPainterPath>
#include <QRegion>
#include <QSequentialAnimationGroup>
#include <QPropertyAnimation>
QTanTanScanning::QTanTanScanning(QWidget *parent) : QWidget(parent)
{
ringMaxR = 95;
ringColor = QColor(255, 0, 0);
scannigColor = QColor(255, 0, 0);
m_pressflag = false;
centerRingR = 20;//中心图片大小
centerR = 20;//中心图片大小
ringPenWidthStep = 0.01;
ringsRStep = 1;
ringsAlphaStep = 255 / ringMaxR;
m_Timer = new QTimer(this);
connect(m_Timer, SIGNAL(timeout()), this, SLOT(mTimeout()));
m_Timer->start(1000);
ringsTimer = new QTimer(this);
ringsTimer->setInterval(50);//波形快慢
connect(ringsTimer, SIGNAL(timeout()), this, SLOT(ringsTimerWork()));
ringsTimer->start();
QPropertyAnimation *anim1 = new QPropertyAnimation(this, "");
anim1->setStartValue(20);//开始值40
anim1->setEndValue(25);//结束值50
anim1->setDuration(500);//持续时间
QPropertyAnimation *anim2 = new QPropertyAnimation(this, "");
anim2->setStartValue(25);
anim2->setEndValue(15);
anim2->setDuration(500);//持续时间
QPropertyAnimation *anim3 = new QPropertyAnimation(this, "");
anim3->setStartValue(15);
anim3->setEndValue(20);
anim3->setDuration(500);//持续时间
//动画组 动画效果依次运行
animationGroup = new QSequentialAnimationGroup() ;
animationGroup->addAnimation(anim1);
animationGroup->addAnimation(anim2);
animationGroup->addAnimation(anim3);
connect(anim1, SIGNAL(valueChanged(QVariant)), this, SLOT(updateRadius(QVariant)));
connect(anim2, SIGNAL(valueChanged(QVariant)), this, SLOT(updateRadius(QVariant)));
connect(anim3, SIGNAL(valueChanged(QVariant)), this, SLOT(updateRadius(QVariant)));
mTimeout();
}
void QTanTanScanning::updateRadius(QVariant radius)
{
//如果鼠标悬停则逐渐变小,鼠标移开则逐渐变大直到恢复
centerR = radius.toInt();
update();
}
void QTanTanScanning::ringsTimerWork()
{
QVector<struct RingData>::iterator iter = rings.begin();
while(iter != rings.end())
{
struct RingData currRing = *iter;
if(currRing.radius < ringMaxR)
{
currRing.radius += ringsRStep;
currRing.alpha = currRing.radius * (255 / ringMaxR);
currRing.penWidth = 3.0 - currRing.radius * (3.0 / ringMaxR);
*iter = currRing;
iter++;
}
else
{
rings.erase(iter);
}
}
update();
}
void QTanTanScanning::mTimeout()
{
animationGroup->start();
QMatrix qMatrix;
int width = this->width();
int height = this->height();
int side = qMin(width, height);
qMatrix.scale(side / 200.0, side / 200.0);
QRegion mEllipse = QRegion(-centerRingR, -centerRingR, centerRingR * 2, centerRingR * 2, QRegion::Ellipse);
mEllipse = qMatrix.map(mEllipse);
struct RingData ring;
ring.radius = centerRingR;
ring.alpha = 255;
ring.penWidth = 10;
rings.push_back(ring);
update();
}
void QTanTanScanning::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
//绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0);
drawRings(&painter);
drawCenterRing(&painter);
}
void QTanTanScanning::drawRings(QPainter *painter)
{
painter->save();
painter->setBrush(Qt::NoBrush);
QVector<struct RingData>::iterator iter = rings.begin();
while(iter != rings.end())
{
struct RingData currRing = *iter;
int radius = currRing.radius;
//绘制圆弧方法绘制圆环
float penWidth = currRing.penWidth;
QRectF rect(-radius + penWidth / 2, -radius + penWidth / 2, radius * 2 - penWidth, radius * 2 - penWidth);
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
ringColor.setAlpha(255 - currRing.alpha);
QPen pen(ringColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
//绘制总范围角度圆弧
pen.setColor(ringColor);
painter->setPen(pen);
if(penWidth > 0){
painter->drawArc(rect, 0 * 16, 360 * 16);
}
iter++;
}
painter->restore();
}
void QTanTanScanning::drawCenterRing(QPainter *painter)
{
painter->save();
QPixmap pixmap(":/image/bg.jpg");
QPainterPath path;
path.addEllipse(QPoint(0, 0), centerR, centerR);
painter->setClipPath(path);
QRect rect(-centerR, -centerR, centerR * 2, centerR * 2);
painter->drawPixmap(rect, pixmap);
int penWidth = 3;
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
QPen pen(Qt::white, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
painter->setPen(pen);
painter->drawArc(rect, 0, 360 * 16);
painter->restore();
}
QSize QTanTanScanning::sizeHint() const
{
return QSize(100, 100);
}
QSize QTanTanScanning::minimumSizeHint() const
{
return QSize(50, 50);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
#ifndef QTANTANSCANNING_H
#define QTANTANSCANNING_H
#include <QWidget>
#include <QVariant>
#include <QDebug>
struct RingData
{
int radius;
int alpha;
float penWidth;
};
class QSequentialAnimationGroup;
class QTanTanScanning : public QWidget
{
Q_OBJECT
public:
explicit QTanTanScanning(QWidget *parent = nullptr);
public:
QSize sizeHint() const;
QSize minimumSizeHint() const;
protected:
void paintEvent(QPaintEvent *);
void drawRings(QPainter *painter);//扩散效果
void drawCenterRing(QPainter *painter);//中间效果
signals:
public slots:
void mTimeout();
private slots:
void ringsTimerWork();
void updateRadius(QVariant radius);
private:
QTimer *m_Timer; //扩散圈定时器
QTimer *ringsTimer; //扩散圈定时器
QColor ringColor; //扩散圈颜色
QColor scannigColor; //扫描线颜色
int ringMaxR; //最大半径
QVector<QPair<int, int>> ringsR2Alpha; //扩散圈的大小与透明度
bool m_pressflag; //判断按钮是否被点击
int centerRingR; //圆形按钮的半径
int centerR;
QVector<struct RingData> rings;
float ringPenWidthStep;
float ringsRStep;
float ringsAlphaStep;
QSequentialAnimationGroup *animationGroup; //动画对象
};
#endif // QTANTANSCANNING_H
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.