QT 界面设计篇(水波纹进度条QProgressBarWater)

效果图:

头文件声明(QProgressBarWater.h):

#ifndef QPROGRESSBARWATER_H
#define QPROGRESSBARWATER_H

#include <QWidget>
#include <QPainter>
#include <QPaintEvent>

class QProgressBarWater : public QWidget
{
    Q_OBJECT

public:
    explicit QProgressBarWater(QWidget *parent = nullptr);

    enum PercentStyle_Type{
        PercentStyle_Rect = 0,  //矩形
        PercentStyle_Circle,    //圆
        PercentStyle_Ellipse,   //椭圆
    };

signals:

public slots:

protected:
    virtual void paintEvent(QPaintEvent *event);
    virtual void timerEvent(QTimerEvent *event);

private:
    PercentStyle_Type m_percentStyle = PercentStyle_Rect;
    QColor m_frontColor = Qt::green;
    QColor m_textColor = Qt::white;
    QColor m_boderColor = Qt::white;
    QColor m_bgColor = QColor(0, 200, 0, 200);
    QFont m_font;
    int m_value = 50;
    int m_minValue = 0;
    int m_maxValue = 100;
    int m_waterDensity = 1;
    double m_waterHeight = 0.03;
    double m_offset = 50;
    int m_borderWidth = 0;


    void drawValue(QPainter *painter);

public:
    void setValue(int value);
    int value();
    void setMaxValue(int value);
    int maxValue();
    void setMinValue(int value);
    int minValue();
    void setPercentStyle(QProgressBarWater::PercentStyle_Type type);
    PercentStyle_Type percentStyle();
    void setWaterDensity(int val);
    int waterDensity();
    void setColor(QColor col);
    QColor color();
    void setWaterHeight(double val);
    double waterHeight();
    void setBorderWidth(int val);
    int borderWidth();
    void setTextColor(QColor col);
    QColor textColor();
    void setBoderColor(QColor col);
    QColor boderColor();
    void setBgColor(QColor col);
    QColor bgColor();
};

#endif // QPROGRESSBARWATER_H

源码定义(QProgressBarWater.cpp):

#include "QProgressBarWater.h"
#include <QPainter>
#include <qmath.h>
#include <QBrush>
#include <QColor>
#include <QLinearGradient>

QProgressBarWater::QProgressBarWater(QWidget *parent) : QWidget(parent)
{
    m_font.setFamily("Microsoft YaHei");
    this->startTimer(80);
}

void QProgressBarWater::setValue(int value)
{
    m_value = qMax(m_minValue, qMin(m_maxValue, value));
}

int QProgressBarWater::value()
{
    return m_value;
}

void QProgressBarWater::setMaxValue(int value)
{
    m_maxValue = value;
}

int QProgressBarWater::maxValue()
{
    return m_maxValue;
}

void QProgressBarWater::setMinValue(int value)
{
    m_minValue = value;
}

int QProgressBarWater::minValue()
{
    return m_minValue;
}

void QProgressBarWater::setPercentStyle(QProgressBarWater::PercentStyle_Type type)
{
    m_percentStyle = type;
}

QProgressBarWater::PercentStyle_Type QProgressBarWater::percentStyle()
{
    return m_percentStyle;
}

void QProgressBarWater::setWaterDensity(int val)
{
    m_waterDensity = val;
}

int QProgressBarWater::waterDensity()
{
    return m_waterDensity;
}

void QProgressBarWater::setColor(QColor col)
{
    m_frontColor = col;
}

QColor QProgressBarWater::color()
{
    return m_frontColor;
}

void QProgressBarWater::setWaterHeight(double val)
{
    m_waterHeight = val;
}

double QProgressBarWater::waterHeight()
{
    return m_waterHeight;
}

void QProgressBarWater::setBorderWidth(int val)
{
    m_borderWidth = val;
}

int QProgressBarWater::borderWidth()
{
    return m_borderWidth;
}

void QProgressBarWater::setTextColor(QColor col)
{
    m_textColor = col;
}

QColor QProgressBarWater::textColor()
{
    return m_textColor;
}

void QProgressBarWater::setBoderColor(QColor col)
{
    m_boderColor = col;
}

QColor QProgressBarWater::boderColor()
{
    return m_boderColor;
}

void QProgressBarWater::setBgColor(QColor col)
{
    m_bgColor = col;
}

QColor QProgressBarWater::bgColor()
{
    return m_bgColor;
}

void QProgressBarWater::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);

    this->update();
}

void QProgressBarWater::drawValue(QPainter *painter)
{
    Q_UNUSED(painter);
    painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform); // 反锯齿;

    int height = this->height();
    int width = this->width();
    int side = qMin(width, height);

    //计算当前值所占百分比
    double percent = 1 - (double)(m_value - m_minValue) / (m_maxValue - m_minValue);

    //正弦曲线公式 y = A * sin(ωx + φ) + k
    //w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度
    double w = 0.038;//m_waterDensity * M_PI * 1.6/ width;

    //A表示振幅,可以理解为水波的高度,值越大高度越高(越浪 ^_^),取值高度的百分比
    double A = height * m_waterHeight;

    //k表示y轴偏移,可以理解为进度,取值高度的进度百分比
    double k = height * percent;

    //第一条波浪路径集合
    QPainterPath waterPath1;

    //第二条波浪路径集合
    QPainterPath waterPath2;

    //移动到左上角起始点
    waterPath1.moveTo(0, height);
    waterPath2.moveTo(0, height);

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

    double waterY1 = 0.0;
    double waterY2 = 0.0;
    for(int x = 0; x <= width; x++) {
        //第一条波浪Y轴
        waterY1 = (double)(A * qSin(w * x + m_offset)) + k;

        //第二条波浪Y轴
        waterY2 = (double)(A * qSin(w * x + m_offset + (width / 2 * w))) + k;

        //如果当前值为最小值则Y轴为高度
        if (m_value == m_minValue) {
            waterY1 = height;
            waterY2 = height;
        }

        //如果当前值为最大值则Y轴为0
        if (m_value == m_maxValue) {
            waterY1 = 0;
            waterY2 = 0;
        }

        waterPath1.lineTo(x, waterY1);
        waterPath2.lineTo(x, waterY2);
    }

    //移动到右下角结束点,整体形成一个闭合路径
    waterPath1.lineTo(width, height);
    waterPath2.lineTo(width, height);

    //画背景,此处由单一色调改为了渐变色
    QRadialGradient radialGradient(side / 2, height / 2, side / 2, side / 2, side / 2);
    radialGradient.setColorAt(0, QColor(0, 0, 255, 100));
    radialGradient.setColorAt(1.0, QColor(50, 50, 255, 200));

    QPainterPath bigPath;
    if (m_percentStyle == PercentStyle_Rect) {
        width = width - m_borderWidth * 2;
        height = height - m_borderWidth * 2;
        bigPath.addRect(m_borderWidth, m_borderWidth, width, height);
        //painter->setBrush(m_boderColor);
        painter->setBrush(QBrush(radialGradient));
        painter->drawRect(this->rect());
        //painter->setBrush(m_bgColor);
        painter->setBrush(QBrush(radialGradient));
        painter->drawRect(m_borderWidth, m_borderWidth, width, height);
    }
    else if (m_percentStyle == PercentStyle_Circle) {
        //painter->setBrush(m_boderColor);
        painter->setBrush(QBrush(radialGradient));
        painter->drawEllipse((width - side) / 2, (height - side) / 2, side, height);
        side = side - m_borderWidth * 2;
        bigPath.addEllipse((width - side) / 2, m_borderWidth, side, side);
        //painter->setBrush(m_bgColor);
        painter->setBrush(QBrush(radialGradient));
        painter->setPen(m_bgColor);
        painter->drawEllipse((width - side) / 2, m_borderWidth, side, side);
    }
    else if (m_percentStyle == PercentStyle_Ellipse) {
        width = width - m_borderWidth * 2;
        height = height - m_borderWidth * 2;
        bigPath.addEllipse(m_borderWidth, m_borderWidth, width, height);
        //painter->setBrush(m_boderColor);
        painter->setBrush(QBrush(radialGradient));
        painter->drawEllipse(this->rect());
        //painter->setBrush(m_bgColor);
        painter->setBrush(QBrush(radialGradient));
        painter->drawEllipse(m_borderWidth, m_borderWidth, width, height);
    }

    painter->save();

    //新路径,用大路径减去波浪区域的路径,形成遮罩效果
    QPainterPath path;
    painter->setPen(Qt::NoPen);
    QColor waterColor1 = m_frontColor;
    waterColor1.setAlpha(100);
    QColor waterColor2 = m_frontColor;
    waterColor2.setAlpha(180);

    QLinearGradient linearGradient1(0,0,0,side);
    linearGradient1.setColorAt(0.2,QColor(0, 255, 255, 100));
    linearGradient1.setColorAt(0.6,QColor(50, 200, 50, 100));
    linearGradient1.setColorAt(1.0,QColor(25, 150, 25, 100));

    QLinearGradient linearGradient2(0,0,0,side);
    linearGradient2.setColorAt(0.2,QColor(0, 255, 255, 180));
    linearGradient2.setColorAt(0.6,QColor(50, 200, 50, 180));
    linearGradient2.setColorAt(1.0,QColor(25, 150, 25, 180));

    //第一条波浪挖去后的路径
    path = bigPath.intersected(waterPath1);
    painter->setBrush(QBrush(linearGradient1));
    painter->drawPath(path);

    //第二条波浪挖去后的路径
    path = bigPath.intersected(waterPath2);
    painter->setBrush(QBrush(linearGradient2));
    painter->drawPath(path);
    painter->restore();

    //绘制文字
    m_font.setPixelSize(this->width()/4);
    painter->setPen(m_textColor);
    painter->setFont(m_font);
    painter->drawText(this->rect(), Qt::AlignCenter, QString("%0%").arg(QString::number(m_value)));
}

void QProgressBarWater::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    drawValue(&painter);
}

猜你喜欢

转载自blog.csdn.net/u012156872/article/details/110396056