天天看點

Qt控件:動态波浪與進度顯示

1. 預覽圖

Qt控件:動态波浪與進度顯示

2. 代碼

頭檔案

#ifndef WATERPROCESSBAR_H
#define WATERPROCESSBAR_H

#include <QWidget>
#include <QPainter>
#include <QTimer>
#include <QtMath>


class WaterProcessBar : public QWidget
{
    Q_OBJECT
public:
    explicit WaterProcessBar(QWidget *parent = nullptr);



private:
    void drawBg(QPainter *painter);
    void drawProcess(QPainter *painter);
    void drawValue(QPainter *painter);
    void timeout();
private:
    QTimer *timer;
    QColor m_textColor;
    QColor m_borderColor;
    QColor m_bgColor;
    QColor m_usedColor;
    QColor m_usedColor_lowbattery;
    int m_value;
    int m_minValue;
    int m_maxValue;
    int m_waterDensity;
    double m_waterHeight;
    double m_offset;
    int m_borderWidth;

protected:
    void paintEvent(QPaintEvent *event);
signals:

};

#endif // WATERPROCESSBAR_H

           

源檔案

#include "waterprocessbar.h"

WaterProcessBar::WaterProcessBar(QWidget *parent) : QWidget(parent)
{   
    m_value = 50;//百分之比變量
    m_minValue = 0;
    m_maxValue = 100;
    m_waterDensity = 10; // 水波的密度
    m_waterHeight = 0.07;
    m_offset = 50;
    m_borderWidth = 10;
    m_textColor = Qt::white;
    m_borderColor = Qt::black;
    m_bgColor = Qt::gray;
    m_usedColor = QColor(0,255,127);
    m_usedColor_lowbattery = QColor(255,69,0);
    timer = new QTimer(this);
    timer->start(80);
    connect(timer,&QTimer::timeout,this,&WaterProcessBar::timeout);
}


void WaterProcessBar::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //背景
    drawBg(&painter);

    //進度、水波
    drawProcess(&painter);

    //進度數字
    drawValue(&painter);
}

void WaterProcessBar::drawBg(QPainter *painter)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height) - m_borderWidth;

    int startX = (width - side) * 0.5;
    int startY = (height - side) * 0.5;

    painter->save();
    painter->setBrush(QBrush(m_bgColor));
    if (m_borderWidth == 0)
    {
        painter->setPen(Qt::NoPen);
    }
    else
    {
        QBrush brush(m_borderColor);
        painter->setPen(QPen(brush, m_borderWidth, Qt::SolidLine));
    }

    painter->drawEllipse(startX, startY, side, side);
    painter->restore();
}

void WaterProcessBar::drawProcess(QPainter *painter)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height) - (2 * m_borderWidth); //直徑

    int startX = (width - side) * 0.5;
    int startY = (height - side) *0.5;
    int endX = startX + side;
    int endY = startY + side;

    double percent = (m_value * 1.0) / (m_maxValue - m_minValue);

    double w = 2 * M_PI / endX;
    double A = endY * m_waterHeight;
    double k = endY * (1.0 - percent);

    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(m_usedColor);

    QPainterPath totalPath;
    //加入圓形路徑
    totalPath.addEllipse(startX, startY, side, side);

    //水波路徑
    QPainterPath water1;
    QPainterPath water2;

    water1.moveTo(startX, endY);
    water2.moveTo(startX, endY);

    m_offset += 0.6;
    if (m_offset > (endX / 2)) {
        m_offset = 0;
    }

    for(int i = startX; i < endX; i++) {
        //第一條波浪Y軸
        double waterY1 = (double)(A * qSin(w * i + m_offset)) + k;
        //第二條波浪Y軸
        double waterY2;
        waterY2 = (double)(A * qSin(w * i + m_offset + (endX / 2 * w))) + k;

        water1.lineTo(i, waterY1);
        water2.lineTo(i, waterY2);

        if (m_value == m_minValue) {
            waterY1 = endY;
        }

        if (m_value == m_maxValue) {
            waterY1 = startY;
        }
    }
    //封閉
    water1.lineTo(endX, endY);
    water2.lineTo(endX, endY);

    QPainterPath path;

    QColor waterColor1 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
    waterColor1.setAlpha(100);
    QColor waterColor2 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
    waterColor2.setAlpha(200);

    //第一條波浪
    path = totalPath.intersected(water1);
    painter->setBrush(waterColor1);
    painter->drawPath(path);

    //第二條波浪挖去後的路徑
    path = totalPath.intersected(water2);
    painter->setBrush(waterColor2);
    painter->drawPath(path);


    painter->restore();
}

void WaterProcessBar::drawValue(QPainter *painter)
{
    painter->save();
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height) - m_borderWidth;

    int startX = (width - side) * 0.5;
    int startY = (height - side) * 0.5;

    int fontSize = side / 4;


    QFont font;
    font.setFamily("微軟雅黑");
    font.setPixelSize(fontSize);
    font.setBold(true);

    painter->setFont(font);
    painter->setPen(Qt::white);
    painter->drawText(QRectF(startX, startY, side, side), Qt::AlignCenter, QString("%1%").arg(m_value));

    painter->restore();
}

void WaterProcessBar::timeout()
{
    this->update();
}
           

3. 用法

  • 建立類,然後在建立的頭檔案和源檔案裡面添加上述代碼
    Qt控件:動态波浪與進度顯示
    Qt控件:動态波浪與進度顯示
  • 在UI界面裡面拖拽widget部件
    Qt控件:動态波浪與進度顯示
  • 将widget部件提升為自定義的類,在提升的類名稱裡面填入上面源代碼裡面的類名
    Qt控件:動态波浪與進度顯示
  • 調用函數如下,在設計師界面類裡面調用這個函數即可
void GaugePanel::setValue(int value)
{
    setValue(double(value));
}