1. 程式人生 > 其它 >QT 繪製圓形進度條

QT 繪製圓形進度條

在這裡插入圖片描述
一、參考
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();
}