自定義Qt圓形進度條
阿新 • • 發佈:2019-01-02
主要程式碼:
#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(); }
原始碼連結:點選開啟連結