1. 預覽圖
2. 代碼
頭檔案
#ifndef WATERPROCESSBAR_H
#define WATERPROCESSBAR_H
#include <QWidget>
#include <QPainter>
#include <QTimer>
#include <QtMath>
class WaterProcessBar : public QWidget
{
Q_OBJECT
public:
explicit WaterProcessBar(QWidget *parent = nullptr);
private:
void drawBg(QPainter *painter);
void drawProcess(QPainter *painter);
void drawValue(QPainter *painter);
void timeout();
private:
QTimer *timer;
QColor m_textColor;
QColor m_borderColor;
QColor m_bgColor;
QColor m_usedColor;
QColor m_usedColor_lowbattery;
int m_value;
int m_minValue;
int m_maxValue;
int m_waterDensity;
double m_waterHeight;
double m_offset;
int m_borderWidth;
protected:
void paintEvent(QPaintEvent *event);
signals:
};
#endif // WATERPROCESSBAR_H
源檔案
#include "waterprocessbar.h"
WaterProcessBar::WaterProcessBar(QWidget *parent) : QWidget(parent)
{
m_value = 50;//百分之比變量
m_minValue = 0;
m_maxValue = 100;
m_waterDensity = 10; // 水波的密度
m_waterHeight = 0.07;
m_offset = 50;
m_borderWidth = 10;
m_textColor = Qt::white;
m_borderColor = Qt::black;
m_bgColor = Qt::gray;
m_usedColor = QColor(0,255,127);
m_usedColor_lowbattery = QColor(255,69,0);
timer = new QTimer(this);
timer->start(80);
connect(timer,&QTimer::timeout,this,&WaterProcessBar::timeout);
}
void WaterProcessBar::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
//背景
drawBg(&painter);
//進度、水波
drawProcess(&painter);
//進度數字
drawValue(&painter);
}
void WaterProcessBar::drawBg(QPainter *painter)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height) - m_borderWidth;
int startX = (width - side) * 0.5;
int startY = (height - side) * 0.5;
painter->save();
painter->setBrush(QBrush(m_bgColor));
if (m_borderWidth == 0)
{
painter->setPen(Qt::NoPen);
}
else
{
QBrush brush(m_borderColor);
painter->setPen(QPen(brush, m_borderWidth, Qt::SolidLine));
}
painter->drawEllipse(startX, startY, side, side);
painter->restore();
}
void WaterProcessBar::drawProcess(QPainter *painter)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height) - (2 * m_borderWidth); //直徑
int startX = (width - side) * 0.5;
int startY = (height - side) *0.5;
int endX = startX + side;
int endY = startY + side;
double percent = (m_value * 1.0) / (m_maxValue - m_minValue);
double w = 2 * M_PI / endX;
double A = endY * m_waterHeight;
double k = endY * (1.0 - percent);
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(m_usedColor);
QPainterPath totalPath;
//加入圓形路徑
totalPath.addEllipse(startX, startY, side, side);
//水波路徑
QPainterPath water1;
QPainterPath water2;
water1.moveTo(startX, endY);
water2.moveTo(startX, endY);
m_offset += 0.6;
if (m_offset > (endX / 2)) {
m_offset = 0;
}
for(int i = startX; i < endX; i++) {
//第一條波浪Y軸
double waterY1 = (double)(A * qSin(w * i + m_offset)) + k;
//第二條波浪Y軸
double waterY2;
waterY2 = (double)(A * qSin(w * i + m_offset + (endX / 2 * w))) + k;
water1.lineTo(i, waterY1);
water2.lineTo(i, waterY2);
if (m_value == m_minValue) {
waterY1 = endY;
}
if (m_value == m_maxValue) {
waterY1 = startY;
}
}
//封閉
water1.lineTo(endX, endY);
water2.lineTo(endX, endY);
QPainterPath path;
QColor waterColor1 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
waterColor1.setAlpha(100);
QColor waterColor2 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
waterColor2.setAlpha(200);
//第一條波浪
path = totalPath.intersected(water1);
painter->setBrush(waterColor1);
painter->drawPath(path);
//第二條波浪挖去後的路徑
path = totalPath.intersected(water2);
painter->setBrush(waterColor2);
painter->drawPath(path);
painter->restore();
}
void WaterProcessBar::drawValue(QPainter *painter)
{
painter->save();
int width = this->width();
int height = this->height();
int side = qMin(width, height) - m_borderWidth;
int startX = (width - side) * 0.5;
int startY = (height - side) * 0.5;
int fontSize = side / 4;
QFont font;
font.setFamily("微軟雅黑");
font.setPixelSize(fontSize);
font.setBold(true);
painter->setFont(font);
painter->setPen(Qt::white);
painter->drawText(QRectF(startX, startY, side, side), Qt::AlignCenter, QString("%1%").arg(m_value));
painter->restore();
}
void WaterProcessBar::timeout()
{
this->update();
}
3. 用法
- 建立類,然後在建立的頭檔案和源檔案裡面添加上述代碼
- 在UI界面裡面拖拽widget部件
- 将widget部件提升為自定義的類,在提升的類名稱裡面填入上面源代碼裡面的類名
- 調用函數如下,在設計師界面類裡面調用這個函數即可
void GaugePanel::setValue(int value)
{
setValue(double(value));
}