天天看点

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));
}