話不多說,先上效果圖
代碼示例:
#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);設置動畫周期可改變水波速度