1. 程式人生 > >自定義Qt圓形進度條

自定義Qt圓形進度條

主要程式碼:

#include "diaplot.h"
#include "qpainter.h"
#include "qdebug.h"

DialPlot::DialPlot(QWidget *parent) :
    QWidget(parent)
{
    radius = 0;
    minValue = 0;
    maxValue = 100;
    value = 0;
    unit = "";
    centerPoint = QPointF(0, 0);

    textFont = QFont("Arial", 8, QFont::Normal);
    textColor = QColor(255, 255, 255);
    bgColor = QColor(173, 173, 173);
    firstColor = QColor(34, 139, 34);
    secondColor = QColor(238, 238, 0);
    thirdColor = QColor(205, 51, 51);
    centerColor = QColor(94, 94, 94);
}

DialPlot::~DialPlot()
{

}

void DialPlot::paintEvent(QPaintEvent *)
{
    int width = this->width();
    int height = this->height();

    //繪製準備工作,旋轉座標軸中心
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.translate(width / 2, height / 2);

    //更新儀表盤最外圈半徑大小
    radius = width > height ? height : width;
    radius = radius / 2;

    //繪製錶盤背景
    drawBg(&painter);
    //繪製錶盤
    drawDial(&painter);
    //繪製錶盤刻度
    drawTicks(&painter);
    //繪製指標
    drawPointer(&painter);
    //繪製當前值
    drawValue(&painter);
}

void DialPlot::drawBg(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);
    QRadialGradient bgGradient(centerPoint, radius, centerPoint);
    bgGradient.setColorAt(0, bgColor.lighter(100));
    bgGradient.setColorAt(0.6, bgColor.darker(150));
    bgGradient.setColorAt(0.61, bgColor);
    bgGradient.setColorAt(0.8, bgColor.darker(150));
    bgGradient.setColorAt(1, bgColor);
    painter->setBrush(bgGradient);
    painter->drawEllipse(centerPoint, radius, radius);
    painter->restore();
}

void DialPlot::drawDial(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    QPointF pieRectTopLeftPot(- radius, - radius);
    QPointF pieRectBottomRightPot(radius, radius);
    QRectF pieRect = QRectF(pieRectTopLeftPot, pieRectBottomRightPot);

    //將錶盤分割槽間三種不同顏色顯示
    QRadialGradient firstGradient(centerPoint, radius, centerPoint);
    firstGradient.setColorAt(0, Qt::transparent);
    firstGradient.setColorAt(0.6, Qt::transparent);
    firstGradient.setColorAt(0.61, firstColor.darker(150));
    firstGradient.setColorAt(0.8, firstColor.lighter(100));
    firstGradient.setColorAt(1.0, firstColor.darker(150));
    painter->setBrush(firstGradient);
    painter->drawPie(pieRect, 130 * 16, 80 * 16);

    QRadialGradient secondGradient(centerPoint, radius, centerPoint);
    secondGradient.setColorAt(0, Qt::transparent);
    secondGradient.setColorAt(0.6, Qt::transparent);
    secondGradient.setColorAt(0.61, secondColor.darker(150));
    secondGradient.setColorAt(0.8, secondColor.lighter(100));
    secondGradient.setColorAt(1.0, secondColor.darker(150));
    painter->setBrush(secondGradient);
    painter->drawPie(pieRect, 50 * 16, 80 * 16);

    QRadialGradient thirdGradient(centerPoint, radius, centerPoint);
    thirdGradient.setColorAt(0, Qt::transparent);
    thirdGradient.setColorAt(0.6, Qt::transparent);
    thirdGradient.setColorAt(0.61, thirdColor.darker(150));
    thirdGradient.setColorAt(0.8, thirdColor.lighter(100));
    thirdGradient.setColorAt(1.0, thirdColor.darker(150));
    painter->setBrush(thirdGradient);
    painter->drawPie(pieRect, 330 * 16, 80 * 16);

    painter->restore();
}

void DialPlot::drawTicks(QPainter *painter)
{
    painter->save();
    painter->setPen(textColor);

    //刻度長度佔圓盤半徑比例
    double tickRatio = 0.05;

    //旋轉座標軸到刻度起始位置
    painter->rotate(60);

    for (int scale = 0; scale <= 100; ++scale) {
        //逢十的倍數,刻度變長
        tickRatio = scale % 10 ? 0.05 : 0.1;

        //繪製刻度線
        painter->drawLine(QPointF(0, radius * (0.6 - tickRatio)), QPointF(0, radius * 0.6));

        if (scale == 0) {
            //繪製錶盤上最小值
            painter->drawText(-10, radius * (0.38), 20, 10, Qt::AlignCenter, QString::number(minValue));
        } else if (scale == 100) {
            //繪製錶盤上最大值
            painter->drawText(-10, radius * (0.38), 20, 10, Qt::AlignCenter, QString::number(maxValue));
        }

        painter->rotate(2.4);
    }

    painter->restore();
}

void DialPlot::drawPointer(QPainter *painter)
{
    //指標寬度
    int pointerWidth = 6;

    //指標路徑點
    const QPoint pointers[3] = {
        QPoint(centerPoint.x() - pointerWidth / 3, centerPoint.y()),
        QPoint(centerPoint.x() + pointerWidth / 3, centerPoint.y()),
        QPoint(centerPoint.x(), centerPoint.y() - radius)
    };

    painter->save();
    painter->rotate(240);
    painter->setPen(Qt::NoPen);

    //將當前實際值轉換為刻度值
    double first = (double)100 / 3;
    double second = first * 2;
    double currentValue = 100 * (this->value - this->minValue) / (this->maxValue - this->minValue);
    QColor pointerColor = firstColor;

    if (currentValue < first) {
        pointerColor = firstColor;
    } else if (currentValue >= first && currentValue <= second) {
        pointerColor = secondColor;
    } else {
        pointerColor = thirdColor;
    }

    //畫刷顏色設定
    painter->setBrush(pointerColor);

    if (currentValue <= 100) {
        painter->rotate(2.4 * currentValue);
    } else {
        painter->rotate(360);
    }

    painter->drawConvexPolygon(pointers, 3);
    painter->restore();

    //繪製指標中心圓
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(centerColor);
    painter->drawEllipse(QPoint(0, 0), pointerWidth, pointerWidth);
    painter->restore();
}

void DialPlot::drawValue(QPainter *painter)
{
    painter->save();
    painter->setPen(textColor);
    painter->setFont(textFont);
    painter->drawText(QRectF(-30, radius * 0.6 * 0.5, 60, 30), Qt::AlignCenter, QString::number(value) + unit);
    painter->restore();
}

void DialPlot::setRange(double minValue, double maxValue)
{
    //如果最小值大於或者等於最大值則不設定
    if (minValue >= maxValue) {
        return;
    }

    this->minValue = minValue;
    this->maxValue = maxValue;

    //如果目標值不在範圍值內,則重新設定目標值
    if (value < minValue || value > maxValue) {
        setValue(value);
    }

    update();
}

void DialPlot::setRange(int minValue, int maxValue)
{
    setRange((double)minValue, (double)maxValue);
}

void DialPlot::setValue(double value)
{
    //如果目標值比最小值小則取最小值,如果目標值比最大值大則取最大值
    if (value < minValue) {
        this->value = minValue;
    } else if (value > maxValue) {
        this->value = maxValue;
    } else {
        this->value = value;
    }

    update();
    emit valueChanged(value);
}

void DialPlot::setValue(int value)
{
    setValue((double)value);
}

void DialPlot::setUnit(QString unit)
{
    this->unit = unit;
    update();
}

void DialPlot::setTextFont(QFont textFont)
{
    this->textFont = textFont;
    update();
}

void DialPlot::setTextColor(QColor textColor)
{
    this->textColor = textColor;
    update();
}

void DialPlot::setBgColor(QColor bgColor)
{
    this->bgColor = bgColor;
    update();
}

void DialPlot::setFirstColor(QColor firstColor)
{
    this->firstColor = firstColor;
    update();
}

void DialPlot::setSecondColor(QColor secondColor)
{
    this->secondColor = secondColor;
    update();
}

void DialPlot::setThirdColor(QColor thirdColor)
{
    this->thirdColor = thirdColor;
    update();
}

void DialPlot::setCenterColor(QColor centerColor)
{
    this->centerColor = centerColor;
    update();
}

原始碼連結:點選開啟連結