效果图:
头文件声明(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);
}