话不多说,先上效果图
代码示例:
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPropertyAnimation>
#include <QTimer>
#include <cmath>class WaveProgressBar : public QWidget
{Q_OBJECTQ_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)Q_PROPERTY(qreal wavePhase READ wavePhase WRITE setWavePhase)
public:explicit WaveProgressBar(QWidget *parent = nullptr): QWidget(parent), m_min(0), m_max(100), m_value(0),m_wavePhase(0), m_waveAmplitude(10), m_waveLength(150),m_waveColor(QColor(100, 180, 255)){//设置无边框和背景透明//setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Tool);//setAttribute(Qt::WA_TranslucentBackground);// 波浪相位动画QPropertyAnimation *waveAnim = new QPropertyAnimation(this, "wavePhase");waveAnim->setDuration(1000);waveAnim->setStartValue(0);waveAnim->setEndValue(m_waveLength);waveAnim->setLoopCount(-1);waveAnim->start();setMinimumSize(150, 150);resize(150, 150);}int value() const { return m_value; }qreal wavePhase() const { return m_wavePhase; }void setValue(int value){value = qBound(m_min, value, m_max);if (m_value != value) {m_value = value;update();emit valueChanged(m_value);}}void setWavePhase(qreal phase){m_wavePhase = phase;update();}void setWaveColor(const QColor &color){m_waveColor = color;update();}void setWaveAmplitude(const qreal amplitude){m_waveAmplitude = amplitude;}signals:void valueChanged(int value);protected:void paintEvent(QPaintEvent *) override{QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);const qreal side = qMin(width(), height());const QRectF rect(0, 0, side, side);const QPointF center = rect.center();const qreal radius = side / 2.0;// 计算填充进度const qreal progress = (m_value - m_min) / static_cast<qreal>(m_max - m_min);const qreal fillHeight = rect.height() * (1 - progress);// 创建统一背景(使用波浪颜色的深色版本)painter.setPen(Qt::NoPen);painter.setBrush(m_waveColor.darker(150));painter.drawEllipse(center, radius, radius);// 创建波浪路径(始终覆盖整个圆形)QPainterPath wavePath;const qreal waterLevel = fillHeight;const qreal baseY = rect.top() + waterLevel;wavePath.moveTo(rect.left() - m_waveLength, baseY);// 生成波浪曲线for (qreal x = rect.left() - m_waveLength; x < rect.right() + m_waveLength; x += 1.0) {const qreal phase = (x + m_wavePhase) * M_PI / (m_waveLength / 2.0);const qreal y = baseY + m_waveAmplitude * sin(phase);wavePath.lineTo(x, y);}// 闭合路径形成填充区域wavePath.lineTo(rect.bottomRight() + QPointF(m_waveLength, 0));wavePath.lineTo(rect.bottomLeft() - QPointF(m_waveLength, 0));wavePath.closeSubpath();// 创建圆形裁剪路径,控制波浪在圆形区域内QPainterPath clipPath;clipPath.addEllipse(center, radius, radius);painter.setClipPath(clipPath);// 绘制渐变波浪QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());gradient.setColorAt(0, m_waveColor.lighter(120));gradient.setColorAt(1, m_waveColor.darker(120));painter.setBrush(gradient);painter.drawPath(wavePath);// 绘制中心文本painter.setPen(Qt::white);painter.setFont(QFont("Arial", radius * 0.35, QFont::Bold));painter.drawText(rect, Qt::AlignCenter, QString::number(progress * 100, 'f', 0) + "%");}private:int m_min;int m_max;int m_value;qreal m_wavePhase;qreal m_waveAmplitude; //波浪振幅qreal m_waveLength; //波浪长度QColor m_waveColor;
};int main(int argc, char *argv[])
{QApplication a(argc, argv);static int value = 0;WaveProgressBar progressBar;progressBar.show();QTimer timer;QObject::connect(&timer, &QTimer::timeout, &progressBar, [&progressBar](){ progressBar.setValue(++value); });timer.start(1000);return a.exec();
}#include "main.moc"
具体实现效果可自由调整,
m_waveColor代表波浪颜色,示例代码改变m_waveColor亮度绘制背景,可自由修改。
水波效果由波长和振幅控制 “大振幅+长波长=平缓波浪”, “小振幅+短波长=密集波纹”。
通过 waveAnim->setDuration(1000);设置动画周期可改变水波速度