1. 程式人生 > 實用技巧 >Qt QProgressBar美化,水波紋進度條

Qt QProgressBar美化,水波紋進度條

首先上例項

#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(); }