qt自定义控件-水波纹进度条

一、前言

二、环境

qt57 

window10

三、正文

效果

代码

#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++) {
        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_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 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;}//设置水波密度0~100
    int waterDensity() {return m_waterDensity;}//返回水波密度
 
    void setWaterHeight(double val) {m_waterHeight = val;}//设置水波高度0~0.1
    double waterHeight() {return m_waterHeight;}//返回水波高度
 
    void setBorderWidth(int val) {m_borderWidth = val;}//设置边框宽度,占用控件空间,越小越好
    int borderWidth() {return m_borderWidth;}//返回边框宽度

    void setBoderColor(QColor col) {m_boderColor = col;}//设置边框颜色
    QColor boderColor() {return m_boderColor;}//返回边框颜色

    void setColor(QColor col) {m_usedColor = col;}//设置水的颜色
    QColor color() {return m_usedColor;}//返回水的颜色

    void setTextColor(QColor col) {m_textColor = col;}//设置文本颜色
    QColor textColor() {return m_textColor;}//返回文本颜色

    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_boderColor = Qt::black;//边框颜色
    QColor m_usedColor = QColor(180,255,255);//水的颜色
    QColor m_textColor = Qt::white;//文本颜色
    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 "widget.h"
#include <QColorDialog>
#include <QIcon>
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    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("进度"); // 进度
//    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("形状"); // 形状
//    m_percentStyleComboBox = new QComboBox(this);
//    m_percentStyleComboBox->resize(180,30);
//    m_percentStyleComboBox->move(700,40);
//    m_percentStyleComboBox->addItem("矩形"); //
//    m_percentStyleComboBox->addItem("圆形"); //
//    m_percentStyleComboBox->addItem("椭圆"); //
//    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("水波的密度"); //
//    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("背景颜色"); // 背景颜色
//    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("水的高度"); //
//    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(onWaterHeight(int)));
//    m_borderWidthLab = new QLabel(this);
//    m_borderWidthLab->setAlignment(Qt::AlignCenter);
//    m_borderWidthLab->resize(100,30);
//    m_borderWidthLab->move(600,200);
//    m_borderWidthLab->setText("边框宽度"); //
//    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("字体颜色"); //
//    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("边框颜色"); //
//    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("未填充颜色"); //
//    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);
    }
}
#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

四、结语

猜你喜欢

转载自blog.csdn.net/qq_37603131/article/details/113241247