欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt控件:动态波浪与进度显示

程序员文章站 2022-05-28 20:13:57
...

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));
}
ui->控件对象名->setValue(a);