首页 > 其他 > 详细

Qt QProgressBar美化,水波纹进度条

时间:2021-01-21 17:58:06      阅读:313      评论:0      收藏:0      [点我收藏+]

首先上实例

技术分享图片

 

#include <QProgressBar>
#include <QTimer>
#include <QPainter>
#include <QColor>
#include <QtMath>
class WaterProgressBar : public QProgressBar
{
	Q_OBJECT

public:
	WaterProgressBar(QWidget *parent);
	~WaterProgressBar();

protected:
	//页面重绘事件
	void paintEvent(QPaintEvent *event);
private:
	void drawBackGround(QPainter* painter);
	void drawWaterWave(QPainter* painter);
	void drawText(QPainter* painter);

private:
	int m_iBorderWidth;//边框厚度
	int m_iValue;//当前进度条进度
	double m_dOffset;//水波偏移量
	QColor m_waterColor;//水波颜色
	QColor m_backgroundColor;//背景颜色
	QColor m_borderColor;//边框颜色
	QColor m_textColor;//文本颜色
	QTimer *m_timer;//控制水波移动的定时器
};

  

#include "WaterProgressBar.h"

WaterProgressBar::WaterProgressBar(QWidget *parent)
{
    m_iBorderWidth = 10;
    m_waterColor.setRgb(43, 123, 234);
    m_backgroundColor.setRgb(255, 255, 255);
    m_borderColor.setRgb(120, 120, 120);
    m_textColor.setRgb(0, 0, 0);
    m_dOffset = 0;
    //利用定时器固定时间内刷新页面,使得水浪动起来
    m_timer = new QTimer(this);
    m_timer->setSingleShot(false);
    connect(m_timer, &QTimer::timeout, this, [=](){
        if (this->isVisible())
        {
            this->update();
        }
    });
    m_timer->start(50);
}

WaterProgressBar::~WaterProgressBar()
{
}

void WaterProgressBar::paintEvent(QPaintEvent *event)
{
    //进度条不可见的情况下就不重绘了
    if (!this->isVisible())
    {
        return;
    }
    m_iValue = this->value() < 0 ? 0 : this->value();//初始化时QT进度条的进度为-1,避免负进度的出现

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);//开启图和字体抗锯齿

    drawBackGround(&painter);//绘制背景
    drawWaterWave(&painter);//绘制水波
    drawText(&painter);//绘制进度文本
}

void WaterProgressBar::drawBackGround(QPainter* painter)
{
    int width = this->width();
    int height = this->height();
    if (m_iBorderWidth > 0)
    {
        //根据窗口的长宽最小值得到外部背景直径
        int max_diameter = qMin(width, height);
        painter->save();
        painter->setBrush(QBrush(m_borderColor));
        painter->setPen(Qt::NoPen);
        //绘制边框背景,然后用内部背景覆盖,即可得到边框
        painter->drawEllipse(0, 0, max_diameter, max_diameter);
        painter->restore();
    }

    //根据窗口的长宽最小值减去边框厚度得到内部背景直径
    int min_diameter = qMin(width, height) - (2 * m_iBorderWidth);
    painter->setBrush(QBrush(m_backgroundColor));
    painter->setPen(Qt::NoPen);
    painter->drawEllipse(m_iBorderWidth, m_iBorderWidth, min_diameter, min_diameter);
    painter->restore();
}

void WaterProgressBar::drawWaterWave(QPainter* painter)
{
    int width = this->width();
    int height = this->height();
    //根据窗口的长宽最小值减去边框厚度得到直径
    int diameter = qMin(width, height) - (2 * m_iBorderWidth);

    //sincos曲线的波峰,波峰越大,水浪越高
    double waveHeight = 0.04*diameter;
    //sincos曲线的周期,周期越小,水浪越密
    double cycle = 2 * M_PI /diameter;
    //谁的高度,可以理解为进度 
    double percent = (double)m_iValue / 100;
    double waterHeight = (1 - percent)*diameter + m_iBorderWidth;

    painter->save();
    QPainterPath totalPath;
    //加入圆形路径
    totalPath.addEllipse(m_iBorderWidth, m_iBorderWidth, diameter, diameter);

    //水波路径,先画浅色,再画深色
    QPainterPath water1;
    QPainterPath water2;

    water1.moveTo(m_iBorderWidth, m_iBorderWidth + diameter);
    water2.moveTo(m_iBorderWidth, m_iBorderWidth + diameter);

    //偏移量控制
    m_dOffset += 0.3;
    if (m_dOffset > 2*M_PI) 
    {
        m_dOffset = 0;
    }

    for (int i = m_iBorderWidth; i <=m_iBorderWidth+diameter; i++) 
    {
        double waterY1 = 0;
        double waterY2 = 0;

        if (m_iValue == 0)
        {
            waterY1 = waterY2 = waterHeight;
        }
        else if (m_iValue == 100)
        {
            waterY1 = waterY2 = waterHeight;
        }
        else
        {
            //第一条波浪Y轴
            waterY1 = (double)(waveHeight * qSin(cycle * (i - m_iBorderWidth) - M_PI / 2 + m_dOffset)) + waterHeight;//当正弦曲线前进π/2,sin的波峰和cos的波谷就对上了
            //第二条波浪Y轴
            waterY2 = (double)(waveHeight * qCos(cycle * (i - m_iBorderWidth) + m_dOffset)) + waterHeight;
        }
        water1.lineTo(i, waterY1);
        water2.lineTo(i, waterY2);

    }

    //封闭
    water1.lineTo(m_iBorderWidth + diameter, m_iBorderWidth + diameter);
    water2.lineTo(m_iBorderWidth + diameter, m_iBorderWidth + diameter);

    QPainterPath path;
    QColor waterColor1 = m_waterColor;
    waterColor1.setAlpha(100);
    QColor waterColor2 = m_waterColor;
    waterColor2.setAlpha(200);

    //第一条波浪
    path = totalPath.intersected(water1);
    painter->setBrush(waterColor1);
    painter->setPen(Qt::NoPen);
    painter->drawPath(path);

    //第二条波浪挖去后的路径
    path = totalPath.intersected(water2);
    painter->setBrush(waterColor2);
    painter->setPen(Qt::NoPen);
    painter->drawPath(path);

    painter->restore();
}

void WaterProgressBar::drawText(QPainter* painter)
{
    painter->save();
    int width = this->width();
    int height = this->height();
    //根据窗口的长宽最小值减去边框厚度得到直径
    int diameter = qMin(width, height) - (2 * m_iBorderWidth);
    int fontSize = diameter / 5;
    //设置文本字体
    QFont font;
    font.setFamily("微软雅黑");
    font.setPixelSize(fontSize);
    font.setBold(true);
    //绘制文本
    painter->setFont(font);
    painter->setPen(m_textColor);
    painter->drawText(QRectF(m_iBorderWidth, m_iBorderWidth, diameter, diameter), Qt::AlignCenter, QString("%1%").arg(m_iValue));
    painter->restore();
}

 

Qt QProgressBar美化,水波纹进度条

原文:https://www.cnblogs.com/suxia/p/14308645.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!