qt水波进度控件设计

效果:
在这里插入图片描述在这里插入图片描述

代码:
h文件

#ifndef WAVEPROGRESSBAR_H
#define WAVEPROGRESSBAR_H


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

class WaveProgressBar : public QWidget
{
    
    
    Q_OBJECT
public:
    explicit WaveProgressBar(QWidget *parent = 0);

    enum Style_Type{
    
    
        eStyle_Rect = 0,//矩形
        eStyle_Circle,//圆
    };
    //进度值
    void setValue(int value) {
    
    m_value = value;}
    int value() {
    
    return m_value;}
    //最大值
    void setMaxValue(int value) {
    
    m_maxValue = value;}
    int maxValue() {
    
    return m_maxValue;}
    //最小值
    void setMinValue(int value) {
    
    m_minValue = value;}
    int minValue() {
    
    return m_minValue;}
    //设置外框形状
    void setPercentStyle(WaveProgressBar::Style_Type type) {
    
    m_percentStyle = type;}
    Style_Type percentStyle() {
    
    return m_percentStyle;}
    //设置水波密度(周期)
    void setWaterDensity(int val) {
    
    m_waterDensity = val;}
    int waterDensity() {
    
    return m_waterDensity;}
    //设置水体颜色
    void setColor(QColor col) {
    
    m_usedColor = col;}
    QColor color() {
    
    return m_usedColor;}
    //设置水波高度(幅值)
    void setWaterHeight(double val) {
    
    m_waterHeight = val;}
    double waterHeight() {
    
    return m_waterHeight;}
    //设置边界宽度
    void setBorderWidth(int val) {
    
    m_borderWidth = val;}
    int borderWidth() {
    
    return m_borderWidth;}
    //设置边框圆角
    void setRound(int round){
    
    m_round = round;}
    //设置字体颜色
    void setTextColor(QColor col) {
    
    m_textColor = col;}
    QColor textColor() {
    
    return m_textColor;}
    //设置字体边框颜色
    void setBoderColor(QColor col) {
    
    m_boderColor = col;}
    QColor boderColor() {
    
    return m_boderColor;}
    //设置背景颜色
    void setBgColor(QColor col) {
    
    m_bgColor = col;}
    QColor bgColor() {
    
    return m_bgColor;}

    //设置刷新间隔,越小刷新速度越快,cpu消耗越大
    void setUpdateTime(int time){
    
    m_updateTime = time;this->startTimer(m_updateTime);}
    //设置波浪移动速度
    void setSpeed(int speed){
    
    m_speed = speed;}

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

    Style_Type m_percentStyle = eStyle_Rect;   //边框类型
    int m_borderWidth = 0;                                  //边框宽度
    QColor m_boderColor = QColor(0,0,0,80);                 //边框颜色
    int m_round = 5;                                        //边框圆角

    QColor m_usedColor = QColor(180,255,255);               //水体颜色
    QColor m_textColor = Qt::white;                         //字体颜色
    QColor m_bgColor = Qt::gray;                            //背景颜色

    int m_updateTime = 100;         //水波波动速度,越大越慢
    int m_waterDensity = 5;         // 水波的密度
    double m_waterHeight = 0.02;    //水波高度
    double m_offset = 50;           //水波相位差
    double m_speed = 0.4;           //一次刷新的位移,可代表波浪移动速度

    QFont m_font;       //字体,默认大小为控件大小的1/4

    int m_value = 66;
    int m_minValue = 0;
    int m_maxValue = 100;
};

#endif // WAVEPROGRESSBAR_H

cpp文件

#include "waveprogressbar.h"


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

void WaveProgressBar::paintEvent(QPaintEvent *event)
{
    
    
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
    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
    double w = m_waterDensity * M_PI / width;   //w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度
    double A = height * m_waterHeight;  //A表示振幅,可以理解为水波的高度,值越大高度越高(越浪 ^_^),取值高度的百分比
    double k = height * percent;    //k表示y轴偏移,可以理解为进度,取值高度的进度百分比

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

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

    m_offset += m_speed;
    if (m_offset > (width / 2))
        m_offset = 0;

    //计算路劲
    for(int x = 0; x <= width; x++)
    {
    
    
        double waterY1 = (double)(A * sin(w * x + m_offset)) + k; //第一条波浪Y轴
        double waterY2 = (double)(A * sin(w * x + m_offset + (width / 2 * w))) + k; //第二条波浪Y轴
        if (m_value == m_minValue)   //如果当前值为最小值则Y轴为高度
        {
    
    
            waterY1 = height;
            waterY2 = height;
        }
        if (m_value == m_maxValue)  //如果当前值为最大值则Y轴为0
        {
    
    
            waterY1 = 0;
            waterY2 = 0;
        }
        waterPath1.lineTo(x, waterY1);
        waterPath2.lineTo(x, waterY2);
    }
    //移动到右下角结束点,整体形成一个闭合路径
    waterPath1.lineTo(width, height);
    waterPath2.lineTo(width, height);

    //大路径
    QPainterPath bigPath;
    if(m_borderWidth <= 0)
        painter.setPen(Qt::NoPen);
    else
        painter.setPen(m_boderColor);
    painter.setBrush(m_bgColor);
    if (m_percentStyle == eStyle_Rect)
    {
    
    
        painter.setBrush(m_bgColor);
        painter.drawRoundRect(m_borderWidth, m_borderWidth, width, height,5,5);
        bigPath.addRoundRect(m_borderWidth, m_borderWidth, width, height,5,5);
    }
    else if (m_percentStyle == eStyle_Circle)
    {
    
    
        side = side - m_borderWidth * 2;
        painter.drawEllipse((width - side) / 2, m_borderWidth, side, side);
        bigPath.addEllipse((width - side) / 2, m_borderWidth, side, side);
    }

    //新路径,用大路径减去波浪区域的路径,形成遮罩效果
    QPainterPath path;

    //第一条波浪挖去后的路径
    m_usedColor.setAlpha(100);
    path = bigPath.intersected(waterPath1);
    painter.setPen(Qt::NoPen);
    painter.setBrush(m_usedColor);
    painter.drawPath(path);

    //第二条波浪挖去后的路径
    m_usedColor.setAlpha(180);
    path = bigPath.intersected(waterPath2);
    painter.setBrush(m_usedColor);
    painter.drawPath(path);

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

void WaveProgressBar::timerEvent(QTimerEvent *event)
{
    
    
    Q_UNUSED(event);
    this->update();
}

おすすめ

転載: blog.csdn.net/weixin_42887343/article/details/121080339