QT 繪製圓形進度條
阿新 • • 發佈:2020-12-11
一、參考
feiyangqingyun
二、程式碼
#ifndef PROGRESSRING_H
#define PROGRESSRING_H
#include <QWidget>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class ProgressRing; }
QT_END_NAMESPACE
class ProgressRing : public QWidget
{
Q_OBJECT
public:
ProgressRing(QWidget *parent = nullptr );
~ProgressRing();
void setValue(int value);
protected:
void paintEvent(QPaintEvent *);
void drawBg(QPainter *painter);
void drawRing(QPainter *painter);
void drawPadding(QPainter *painter);
void drawCircle(QPainter *painter);
void drawValue(QPainter *painter);
private :
double minValue = 0; //最小值
double maxValue = 100; //最大值
double value; //目標值
int precision = 0; //精確度,小數點後幾位
bool clockWise = true; //順時針逆時針
bool showPercent = true; //顯示百分比
int alarmMode; //警戒報警模式,進度為不同的顏色
int startAngle = 90; //起始角度
int ringPadding = 5; //圓環間距
int ringWidth = 25; //圓環寬度
QColor bgColor = QColor(255, 255, 255); //背景顏色
QColor textColor = QColor(51, 51, 51); //文字顏色
QColor ringColor = QColor(77, 206, 247); //圓環擴大的顏色(最終顏色)
QColor ringBgColor = QColor(255, 255, 255); //圓環收縮的背景(初始顏色)
QColor circleColor= QColor(245, 245, 245); //中心圓顏色
int ringValue1; //環形值1
int ringValue2; //環形值2
int ringValue3; //環形值3
QColor ringColor1; //環形顏色1
QColor ringColor2; //環形顏色2
QColor ringColor3; //環形顏色3
bool reverse = false; //是否往回走
double currentValue = 0; //當前值
QTimer *timer; //定時器繪製動畫
int v = 0;
};
#endif // PROGRESSRING_H
#include "ProgressRing.h"
#include <QPainter>
#include <QColor>
ProgressRing::ProgressRing(QWidget *parent)
: QWidget(parent)
{
}
ProgressRing::~ProgressRing()
{
}
void ProgressRing::setValue(int value)
{
currentValue = value;
update();
}
void ProgressRing::paintEvent(QPaintEvent *)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
//繪製準備工作,啟用反鋸齒,平移座標軸中心,等比例縮放
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0);
//繪製背景
drawBg(&painter);
//繪製進度
drawRing(&painter);
//繪製間隔,重新繪製一個圓遮住,產生間距效果
if (ringPadding > 0) {
drawPadding(&painter);
}
//繪製中間圓
drawCircle(&painter);
//繪製當前值
drawValue(&painter);
}
void ProgressRing::drawBg(QPainter *painter)
{
int radius = 99;
painter->save();
painter->setPen(Qt::NoPen);
//這裡有個技巧,如果沒有間距則設定成圓環的背景色
painter->setBrush(ringPadding == 0 ? ringBgColor : bgColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void ProgressRing::drawRing(QPainter *painter)
{
int radius = 99 - ringPadding;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(ringColor);
QRectF rect(-radius, -radius, radius * 2, radius * 2);
//計算總範圍角度,當前值範圍角度,剩餘值範圍角度
double angleAll = 360.0;
double angleCurrent = angleAll * ((currentValue - minValue) / (maxValue - minValue));
double angleOther = angleAll - angleCurrent;
//如果逆時針
if (!clockWise) {
angleCurrent = -angleCurrent;
angleOther = -angleOther;
}
//動態設定當前進度顏色
QColor color = ringColor;
if (alarmMode == 1) {
if (currentValue >= ringValue3) {
color = ringColor3;
} else if (currentValue >= ringValue2) {
color = ringColor2;
} else {
color = ringColor1;
}
} else if (alarmMode == 2) {
if (currentValue <= ringValue1) {
color = ringColor1;
} else if (currentValue <= ringValue2) {
color = ringColor2;
} else {
color = ringColor3;
}
}
//繪製當前值餅圓
painter->setBrush(color);
painter->drawPie(rect, (startAngle - angleCurrent) * 16, angleCurrent * 16);
//繪製剩餘值餅圓
painter->setBrush(ringBgColor);
painter->drawPie(rect, (startAngle - angleCurrent - angleOther) * 16, angleOther * 16);
painter->restore();
}
void ProgressRing::drawPadding(QPainter *painter)
{
int radius = 99 - ringWidth - ringPadding;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(bgColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void ProgressRing::drawCircle(QPainter *painter)
{
//文字的區域要減去進度的寬度及間距
int radius = 99 - ringWidth - (ringPadding * 2);
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(circleColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void ProgressRing::drawValue(QPainter *painter)
{
//文字的區域要減去進度的寬度及間距
int radius = 99 - ringWidth - (ringPadding * 2);
painter->save();
painter->setPen(textColor);
QFont font;
int fontSize = radius - (showPercent ? 20 : 6);
font.setPixelSize(fontSize);
painter->setFont(font);
QRectF textRect(-radius, -radius, radius * 2, radius * 2);
QString strValue;
if (showPercent) {
double percent = (currentValue * 100) / (maxValue - minValue);
strValue = QString("%1%").arg(percent, 0, 'f', precision);
} else {
strValue = QString("%1").arg(currentValue, 0, 'f', precision);
}
painter->drawText(textRect, Qt::AlignCenter, strValue);
painter->restore();
}