Qt水波进度条Demo

转自:https://blog.csdn.net/u014597198/article/details/78261275

多谢飞扬青春的博客,看到水波形进度条的效果觉得非常不错,于是自己也模仿着做了一个类似的,效果图:

代码:https://download.csdn.net/download/pingis58/10856222

原理:

利用正弦曲线产生平滑曲线点集合,然后用大路径减去当前进度路径,形成水波效果。


源码如下:

    #ifndef SPROGRESSBAR_H
    #define SPROGRESSBAR_H
     
    #include <QWidget>
    #include <QPainter>
    #include <QtMath>
     
    class SProgressBar : public QWidget
    {
        Q_OBJECT
    public:
        explicit SProgressBar(QWidget *parent = 0);
     
        enum PercentStyle_Type{
            PercentStyle_Rect = 0,//矩形
            PercentStyle_Circle,//圆
            PercentStyle_Ellipse,//椭圆
        };
     
        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(SProgressBar::PercentStyle_Type type) {m_percentStyle = type;}
        PercentStyle_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 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;}
    protected:
        void paintEvent(QPaintEvent *event);
        void timerEvent(QTimerEvent *event);
    private:
        PercentStyle_Type m_percentStyle = PercentStyle_Rect;
        QColor m_usedColor = QColor(180,255,255);
        QColor m_textColor = Qt::white;
        QColor m_boderColor = Qt::black;
        QColor m_bgColor = Qt::gray;
        QFont m_font;
        int m_value = 80;
        int m_minValue = 0;
        int m_maxValue = 100;
        int m_waterDensity = 10; // 水波的密度
        double m_waterHeight = 0.03;
        double m_offset = 50;
        int m_borderWidth = 10;
    };
     
    #endif // SPROGRESSBAR_H


    #include "sprogressbar.h"
     
    SProgressBar::SProgressBar(QWidget *parent) : QWidget(parent)
    {
        m_font.setFamily("Microsoft YaHei");
        this->startTimer(80);
    }
     
    void SProgressBar::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
        //w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度
        double w = m_waterDensity * M_PI / 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;
        }
     
        for(int x = 0; x <= width; x++) {
            //第一条波浪Y轴
            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) {
                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);
     
        //大路径
        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.drawRect(this->rect());
            painter.setBrush(m_bgColor);
            painter.drawRect(m_borderWidth, m_borderWidth, width, height);
        } else if (m_percentStyle == PercentStyle_Circle) {
            painter.setBrush(m_boderColor);
            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.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.drawEllipse(this->rect());
            painter.setBrush(m_bgColor);
            painter.drawEllipse(m_borderWidth, m_borderWidth, width, height);
        }
     
        painter.save();
     
        //新路径,用大路径减去波浪区域的路径,形成遮罩效果
        QPainterPath path;
        painter.setPen(Qt::NoPen);
        QColor waterColor1 = m_usedColor;
        waterColor1.setAlpha(100);
        QColor waterColor2 = m_usedColor;
        waterColor2.setAlpha(180);
     
        //第一条波浪挖去后的路径
        path = bigPath.intersected(waterPath1);
        painter.setBrush(waterColor1);
        painter.drawPath(path);
     
        //第二条波浪挖去后的路径
        path = bigPath.intersected(waterPath2);
        painter.setBrush(waterColor2);
        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 SProgressBar::timerEvent(QTimerEvent *event)
    {
        Q_UNUSED(event);
        this->update();
    }


    #ifndef WIDGET_H
    #define WIDGET_H
     
    #include <QWidget>
    #include <QPainter>
    #include <QLabel>
    #include <QSlider>
    #include <QComboBox>
    #include <QPushButton>
    #include "sprogressbar.h"
     
    class Widget : public QWidget
    {
        Q_OBJECT
     
    public:
        Widget(QWidget *parent = 0);
        void initUI();
    private slots:
        void onValueChanged(int value);
        void onPercentStyle(int type);
        void onWaterDesity(int value);
        void onColorClicked();
        void onWaterHeight(int value);
        void onBorderWidth(int value);
        void onTextColorClicked();
        void onBoderColorClicked();
        void onBgColorClicked();
    private:
        SProgressBar *m_progressBar = Q_NULLPTR;
        QLabel* m_valueLab = Q_NULLPTR;
        QSlider* m_valueSlider = Q_NULLPTR;
        QLabel* m_percentStyleLab = Q_NULLPTR;
        QComboBox* m_percentStyleComboBox = Q_NULLPTR;
        QLabel* m_waterDesityLab = Q_NULLPTR;
        QSlider* m_waterDesitySlider = Q_NULLPTR;
        QLabel* m_colorLab = Q_NULLPTR;
        QPushButton* m_colorBtn = Q_NULLPTR;
        QLabel* m_waterHeightLab = Q_NULLPTR;
        QSlider* m_waterHeightSlider = Q_NULLPTR;
        QLabel* m_borderWidthLab = Q_NULLPTR;
        QSlider* m_borderWidthSlider = Q_NULLPTR;
        QLabel* m_textColorLab = Q_NULLPTR;
        QPushButton* m_textColorBtn = Q_NULLPTR;
        QLabel* m_boderColorLab = Q_NULLPTR;
        QPushButton* m_boderColorBtn = Q_NULLPTR;
        QLabel* m_bgColorLab = Q_NULLPTR;
        QPushButton* m_bgColorBtn = Q_NULLPTR;
    };
     
    #endif // WIDGET_H


    #include "widget.h"
    #include <QColorDialog>
    #include <QIcon>
     
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        this->setWindowIcon(QIcon(":/Demo_Hello.ico"));
        this->setWindowTitle("水波纹Demo");
        initUI();
    }
     
    void Widget::initUI()
    {
        this->setFixedSize(900,500);
        m_progressBar = new SProgressBar(this);
        m_progressBar->resize(600,500);
        m_progressBar->move(0,0);
        m_valueLab = new QLabel(this);
        m_valueLab->setAlignment(Qt::AlignCenter);
        m_valueLab->resize(100,30);
        m_valueLab->move(600,0);
        m_valueLab->setText("\350\277\233\345\272\246"); // 进度
        m_valueSlider = new QSlider(this);
        m_valueSlider->setOrientation(Qt::Horizontal);
        m_valueSlider->resize(180,20);
        m_valueSlider->move(700,5);
        m_valueSlider->setMaximum(m_progressBar->maxValue());
        m_valueSlider->setMinimum(m_progressBar->minValue());
        m_valueSlider->setValue(m_progressBar->value());
        connect(m_valueSlider, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)));
        m_percentStyleLab = new QLabel(this);
        m_percentStyleLab->setAlignment(Qt::AlignCenter);
        m_percentStyleLab->resize(100,30);
        m_percentStyleLab->move(600,40);
        m_percentStyleLab->setText("\345\275\242\347\212\266"); // 形状
        m_percentStyleComboBox = new QComboBox(this);
        m_percentStyleComboBox->resize(180,30);
        m_percentStyleComboBox->move(700,40);
        m_percentStyleComboBox->addItem("\347\237\251\345\275\242"); // 矩形
        m_percentStyleComboBox->addItem("\345\234\206\345\275\242"); // 圆形
        m_percentStyleComboBox->addItem("\346\244\255\345\234\206"); // 椭圆
        m_percentStyleComboBox->setCurrentIndex(m_progressBar->percentStyle());
        connect(m_percentStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onPercentStyle(int)));
        m_waterDesityLab = new QLabel(this);
        m_waterDesityLab->setAlignment(Qt::AlignCenter);
        m_waterDesityLab->resize(100,30);
        m_waterDesityLab->move(600,80);
        m_waterDesityLab->setText("\346\260\264\346\263\242\347\232\204\345\257\206\345\272\246"); // 水波的密度
        m_waterDesitySlider = new QSlider(this);
        m_waterDesitySlider->setOrientation(Qt::Horizontal);
        m_waterDesitySlider->resize(180,20);
        m_waterDesitySlider->move(700,85);
        m_waterDesitySlider->setMaximum(100);
        m_waterDesitySlider->setMinimum(0);
        m_waterDesitySlider->setValue(m_progressBar->waterDensity());
        connect(m_waterDesitySlider, SIGNAL(valueChanged(int)), this, SLOT(onWaterDesity(int)));
        m_colorLab = new QLabel(this);
        m_colorLab->setAlignment(Qt::AlignCenter);
        m_colorLab->resize(100,30);
        m_colorLab->move(600,120);
        m_colorLab->setText("\350\203\214\346\231\257\351\242\234\350\211\262"); // 背景颜色
        m_colorBtn = new QPushButton(this);
        m_colorBtn->resize(180,20);
        m_colorBtn->move(700,125);
        QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->color().red())
                .arg(m_progressBar->color().green()).arg(m_progressBar->color().blue());
        m_colorBtn->setStyleSheet(styleCol);
        connect(m_colorBtn, SIGNAL(clicked(bool)),this, SLOT(onColorClicked()));
        m_waterHeightLab = new QLabel(this);
        m_waterHeightLab->setAlignment(Qt::AlignCenter);
        m_waterHeightLab->resize(100,30);
        m_waterHeightLab->move(600,160);
        m_waterHeightLab->setText("\346\260\264\347\232\204\351\253\230\345\272\246"); // 水的高度
        m_waterHeightSlider = new QSlider(this);
        m_waterHeightSlider->setOrientation(Qt::Horizontal);
        m_waterHeightSlider->resize(180,20);
        m_waterHeightSlider->move(700,165);
        m_waterHeightSlider->setMaximum(100);
        m_waterHeightSlider->setMinimum(0);
        m_waterHeightSlider->setValue(m_progressBar->waterHeight()*1000);
        connect(m_waterHeightSlider, SIGNAL(valueChanged(int)), this, SLOT(onWaterDesity(int)));
        m_borderWidthLab = new QLabel(this);
        m_borderWidthLab->setAlignment(Qt::AlignCenter);
        m_borderWidthLab->resize(100,30);
        m_borderWidthLab->move(600,200);
        m_borderWidthLab->setText("\350\276\271\346\241\206\345\256\275\345\272\246"); // 边框宽度
        m_borderWidthSlider = new QSlider(this);
        m_borderWidthSlider->setOrientation(Qt::Horizontal);
        m_borderWidthSlider->resize(180,20);
        m_borderWidthSlider->move(700,205);
        m_borderWidthSlider->setMaximum(20);
        m_borderWidthSlider->setMinimum(0);
        m_borderWidthSlider->setValue(m_progressBar->borderWidth());
        connect(m_borderWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(onBorderWidth(int)));
        m_textColorLab = new QLabel(this);
        m_textColorLab->setAlignment(Qt::AlignCenter);
        m_textColorLab->resize(100,30);
        m_textColorLab->move(600,240);
        m_textColorLab->setText("\345\255\227\344\275\223\351\242\234\350\211\262"); // 字体颜色
        m_textColorBtn = new QPushButton(this);
        m_textColorBtn->resize(180,20);
        m_textColorBtn->move(700,245);
        QString textCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->textColor().red())
                .arg(m_progressBar->textColor().green()).arg(m_progressBar->textColor().blue());
        m_textColorBtn->setStyleSheet(textCol);
        connect(m_textColorBtn, SIGNAL(clicked(bool)),this, SLOT(onTextColorClicked()));
        m_boderColorLab = new QLabel(this);
        m_boderColorLab->setAlignment(Qt::AlignCenter);
        m_boderColorLab->resize(100,30);
        m_boderColorLab->move(600,280);
        m_boderColorLab->setText("\350\276\271\346\241\206\351\242\234\350\211\262"); // 边框颜色
        m_boderColorBtn = new QPushButton(this);
        m_boderColorBtn->resize(180,20);
        m_boderColorBtn->move(700,285);
        QString boderCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->boderColor().red())
                .arg(m_progressBar->boderColor().green()).arg(m_progressBar->boderColor().blue());
        m_boderColorBtn->setStyleSheet(boderCol);
        connect(m_boderColorBtn, SIGNAL(clicked(bool)),this, SLOT(onBoderColorClicked()));
        m_bgColorLab = new QLabel(this);
        m_bgColorLab->setAlignment(Qt::AlignCenter);
        m_bgColorLab->resize(100,30);
        m_bgColorLab->move(600,320);
        m_bgColorLab->setText("\346\234\252\345\241\253\345\205\205\351\242\234\350\211\262"); // 未填充颜色
        m_bgColorBtn = new QPushButton(this);
        m_bgColorBtn->resize(180,20);
        m_bgColorBtn->move(700,325);
        QString bgCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->bgColor().red())
                .arg(m_progressBar->bgColor().green()).arg(m_progressBar->bgColor().blue());
        m_bgColorBtn->setStyleSheet(bgCol);
        connect(m_bgColorBtn, SIGNAL(clicked(bool)),this, SLOT(onBgColorClicked()));
    }
     
    void Widget::onValueChanged(int value)
    {
        m_progressBar->setValue(value);
    }
     
    void Widget::onPercentStyle(int type)
    {
        SProgressBar::PercentStyle_Type index = SProgressBar::PercentStyle_Type(type);
        m_progressBar->setPercentStyle(index);
    }
     
    void Widget::onWaterDesity(int value)
    {
        m_progressBar->setWaterDensity(value);
    }
     
    void Widget::onColorClicked()
    {
        QColor c = QColorDialog::getColor(m_progressBar->color());
        if(c.isValid()) {
            m_progressBar->setColor(c);
            QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());
            m_colorBtn->setStyleSheet(styleCol);
        }
    }
     
    void Widget::onWaterHeight(int value)
    {
        m_progressBar->setWaterHeight(double(value/1000.0));
    }
     
    void Widget::onBorderWidth(int value)
    {
        m_progressBar->setBorderWidth(value);
    }
     
    void Widget::onTextColorClicked()
    {
        QColor c = QColorDialog::getColor(m_progressBar->textColor());
        if(c.isValid()) {
            m_progressBar->setTextColor(c);
            QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());
            m_textColorBtn->setStyleSheet(styleCol);
        }
    }
     
    void Widget::onBoderColorClicked()
    {
        QColor c = QColorDialog::getColor(m_progressBar->boderColor());
        if(c.isValid()) {
            m_progressBar->setBoderColor(c);
            QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());
            m_boderColorBtn->setStyleSheet(styleCol);
        }
    }
     
    void Widget::onBgColorClicked()
    {
        QColor c = QColorDialog::getColor(m_progressBar->bgColor());
        if(c.isValid()) {
            m_progressBar->setBgColor(c);
            QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());
            m_bgColorBtn->setStyleSheet(styleCol);
        }
    }

---------------------
作者:沙振宇
来源:CSDN
原文:https://blog.csdn.net/u014597198/article/details/78261275
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值