效果:
代码:
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();
}