核心代碼來自 feiyangqingyun 大神鏈接:https://blog.csdn.net/feiyangqingyun/article/details/90765642
這邊主要加上大神感覺特別簡單沒有貼出來的代碼,致敬大神
#ifndef GAUGEARC_H
#define GAUGEARC_H
#include <QWidget>
namespace Ui {
class GaugeArc;
}
class GaugeArc : public QWidget
{
Q_OBJECT
Q_ENUMS(PointerStyle)
Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
Q_PROPERTY(double value READ getValue WRITE setValue)
Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
Q_PROPERTY(int scaleMajor READ getScaleMajor WRITE setScaleMajor)
Q_PROPERTY(int scaleMinor READ getScaleMinor WRITE setScaleMinor)
Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle)
Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle)
Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)
Q_PROPERTY(QColor arcColor READ getArcColor WRITE setArcColor)
Q_PROPERTY(QColor scaleColor READ getScaleColor WRITE setScaleColor)
Q_PROPERTY(QColor scaleNumColor READ getScaleNumColor WRITE setScaleNumColor)
Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
Q_PROPERTY(PointerStyle pointerStyle READ getPointerStyle WRITE setPointerStyle)
public:
enum PointerStyle {
PointerStyle_Circle = 0, //圓形指示器
PointerStyle_Indicator = 1, //指針指示器
PointerStyle_IndicatorR = 2, //圓角指針指示器
PointerStyle_Triangle = 3 //三角形指示器
};
explicit GaugeArc(QWidget *parent = nullptr);
~GaugeArc();
protected:
void paintEvent(QPaintEvent *);
void drawArc(QPainter *painter);
void drawScale(QPainter *painter);
void drawScaleNum(QPainter *painter);
void drawPointerCircle(QPainter *painter);
void drawPointerIndicator(QPainter *painter);
void drawPointerIndicatorR(QPainter *painter);
void drawPointerTriangle(QPainter *painter);
void drawRoundCircle(QPainter *painter);
void drawCenterCircle(QPainter *painter);
void drawValue(QPainter *painter);
private slots:
void updateValue();
private:
double minValue = 0; //最小值
double maxValue = 100; //最大值
double value = 0; //目標值
int precision = 1; //精確度,小數點後幾位
int scaleMajor = 10; //大刻度數量
int scaleMinor = 10; //小刻度數量
int startAngle = 45; //開始旋轉角度
int endAngle = 45; //結束旋轉角度
bool animation = 0; //是否啓用動畫顯示
double animationStep = 1; //動畫顯示時步長
QColor arcColor = Qt::green; //圓弧顏色
QColor scaleColor = Qt::green; //刻度尺顏色
QColor scaleNumColor = Qt::green; //刻度值顏色
QColor pointerColor = Qt::red; //指針顏色
QColor textColor = Qt::darkGreen; //文字顏色
PointerStyle pointerStyle = PointerStyle_Indicator; //指針樣式
bool reverse; //是否往回走
double currentValue=0; //當前值
//QTimer *timer; //定時器繪製動畫
public:
double getMinValue() const;
double getMaxValue() const;
double getValue() const;
int getPrecision() const;
int getScaleMajor() const;
int getScaleMinor() const;
int getStartAngle() const;
int getEndAngle() const;
bool getAnimation() const;
double getAnimationStep() const;
QColor getArcColor() const;
QColor getScaleColor() const;
QColor getScaleNumColor() const;
QColor getPointerColor() const;
QColor getTextColor() const;
PointerStyle getPointerStyle() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
public Q_SLOTS:
//設置範圍值
void setRange(double minValue, double maxValue);
void setRange(int minValue, int maxValue);
//設置最大最小值
void setMinValue(double minValue);
void setMaxValue(double maxValue);
//設置目標值
void setValue(double value);
void setValue(int value);
//設置精確度
void setPrecision(int precision);
//設置主刻度數量
void setScaleMajor(int scaleMajor);
//設置小刻度數量
void setScaleMinor(int scaleMinor);
//設置開始旋轉角度
void setStartAngle(int startAngle);
//設置結束旋轉角度
void setEndAngle(int endAngle);
//設置是否啓用動畫顯示
void setAnimation(bool animation);
//設置動畫顯示的步長
void setAnimationStep(double animationStep);
//設置圓弧顏色
void setArcColor(const QColor &arcColor);
//設置刻度尺顏色
void setScaleColor(const QColor &scaleColor);
//設置刻度值顏色
void setScaleNumColor(const QColor &scaleNumColor);
//設置指針顏色
void setPointerColor(const QColor &pointerColor);
//設置文本顏色
void setTextColor(const QColor &textColor);
//設置指針樣式
void setPointerStyle(const PointerStyle &pointerStyle);
Q_SIGNALS:
void valueChanged(int value);
private:
Ui::GaugeArc *ui;
};
#endif // GAUGEARC_H
#include "gaugearc.h"
#include "ui_gaugearc.h"
#include <QPainter>
#include <QtMath>
#include <QTimer>
#include <QDebug>
GaugeArc::GaugeArc(QWidget *parent) :
QWidget(parent),
ui(new Ui::GaugeArc)
{
ui->setupUi(this);
if(this->animation == true)
{
QTimer::singleShot(50, this, SLOT(updateValue()));
}
}
GaugeArc::~GaugeArc()
{
delete ui;
}
void GaugeArc::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);
//繪製圓弧
drawArc(&painter);
//繪製刻度線
drawScale(&painter);
//繪製刻度值
drawScaleNum(&painter);
//根據指示器形狀繪製指示器
if (pointerStyle == PointerStyle_Circle) {
drawPointerCircle(&painter);
} else if (pointerStyle == PointerStyle_Indicator) {
drawPointerIndicator(&painter);
} else if (pointerStyle == PointerStyle_IndicatorR) {
drawPointerIndicatorR(&painter);
} else if (pointerStyle == PointerStyle_Triangle) {
drawPointerTriangle(&painter);
}
//繪製指針中心圓外邊框
drawRoundCircle(&painter);
//繪製指針中心圓
drawCenterCircle(&painter);
//繪製當前值
drawValue(&painter);
}
void GaugeArc::drawArc(QPainter *painter)
{
int radius = 98;
painter->save();
QPen pen;
pen.setColor(arcColor);
pen.setWidthF(2);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
//計算總範圍角度,當前值範圍角度,剩餘值範圍角度
double angleAll = 360.0 - startAngle - endAngle;
double angleCurrent = angleAll * ((currentValue - minValue) / (maxValue - minValue));
double angleOther = angleAll - angleCurrent;
//繪製外邊框圓弧
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
painter->drawArc(rect, (270 - startAngle - angleCurrent) * 16, angleCurrent * 16);
painter->drawArc(rect, (270 - startAngle - angleCurrent - angleOther) * 16, angleOther * 16);
//繪製裏邊框圓弧
radius = 90;
rect = QRectF(-radius, -radius, radius * 2, radius * 2);
painter->drawArc(rect, (270 - startAngle - angleCurrent) * 16, angleCurrent * 16);
painter->drawArc(rect, (270 - startAngle - angleCurrent - angleOther) * 16, angleOther * 16);
painter->restore();
}
void GaugeArc::drawScale(QPainter *painter)
{
int radius = 97;
painter->save();
painter->rotate(startAngle);
int steps = (scaleMajor * scaleMinor);
double angleStep = (360.0 - startAngle - endAngle) / steps;
QPen pen;
pen.setColor(scaleColor);
pen.setCapStyle(Qt::RoundCap);
for (int i = 0; i <= steps; i++) {
if (i % scaleMinor == 0) {
pen.setWidthF(1.5);
painter->setPen(pen);
painter->drawLine(0, radius - 12, 0, radius);
} else {
pen.setWidthF(1.0);
painter->setPen(pen);
painter->drawLine(0, radius - 5, 0, radius);
}
painter->rotate(angleStep);
}
painter->restore();
}
void GaugeArc::drawScaleNum(QPainter *painter)
{
int radius = 75;
painter->save();
painter->setPen(scaleNumColor);
double startRad = (360 - startAngle - 90) * (M_PI / 180);
double deltaRad = (360 - startAngle - endAngle) * (M_PI / 180) / scaleMajor;
for (int i = 0; i <= scaleMajor; i++) {
double sina = qSin(startRad - i * deltaRad);
double cosa = qCos(startRad - i * deltaRad);
double value = 1.0 * i * ((maxValue - minValue) / scaleMajor) + minValue;
QString strValue = QString("%1").arg((double)value, 0, 'f', precision);
double textWidth = fontMetrics().width(strValue);
double textHeight = fontMetrics().height();
int x = radius * cosa - textWidth / 2;
int y = -radius * sina + textHeight / 4;
painter->drawText(x, y, strValue);
}
painter->restore();
}
void GaugeArc::drawPointerCircle(QPainter *painter)
{
int radius = 8;
int offset = 30;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
painter->rotate(startAngle);
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawEllipse(-radius, radius + offset, radius * 2, radius * 2);
painter->restore();
}
void GaugeArc::drawPointerIndicator(QPainter *painter)
{
int radius = 75;
painter->save();
painter->setOpacity(0.8);
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
QPolygon pts;
pts.setPoints(3, -5, 0, 5, 0, 0, radius);
painter->rotate(startAngle);
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawConvexPolygon(pts);
painter->restore();
}
void GaugeArc::drawPointerIndicatorR(QPainter *painter)
{
int radius = 75;
painter->save();
QPen pen;
pen.setWidthF(1);
pen.setColor(pointerColor);
painter->setPen(pen);
painter->setBrush(pointerColor);
QPolygon pts;
pts.setPoints(3, -5, 0, 5, 0, 0, radius);
painter->rotate(startAngle);
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawConvexPolygon(pts);
//增加繪製圓角直線,與之前三角形重疊,形成圓角指針
pen.setCapStyle(Qt::RoundCap);
pen.setWidthF(4);
painter->setPen(pen);
painter->drawLine(0, 0, 0, radius);
painter->restore();
}
void GaugeArc::drawPointerTriangle(QPainter *painter)
{
int radius = 10;
int offset = 55;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
QPolygon pts;
pts.setPoints(3, -5, 0 + offset, 5, 0 + offset, 0, radius + offset);
painter->rotate(startAngle);
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawConvexPolygon(pts);
painter->restore();
}
void GaugeArc::drawRoundCircle(QPainter *painter)
{
int radius = 12;
painter->save();
painter->setOpacity(0.5);
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void GaugeArc::drawCenterCircle(QPainter *painter)
{
int radius = 8;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void GaugeArc::drawValue(QPainter *painter)
{
int radius = 100;
painter->save();
painter->setPen(textColor);
QFont font;
font.setPixelSize(30);
painter->setFont(font);
// QRectF textRect(-radius, radius / 2, radius * 2, radius / 3);
QRectF textRect(-radius/3, radius / 2, radius/3*2, radius / 3);
painter->drawRect(textRect); //增加一個矩形框
QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
painter->drawText(textRect, Qt::AlignCenter, strValue);
painter->restore();
}
double GaugeArc::getMinValue()const
{
return this->minValue;
}
double GaugeArc::getMaxValue()const
{
return this->maxValue;
}
double GaugeArc::getValue()const
{
return this->currentValue;
}
int GaugeArc::getPrecision()const
{
return this->precision;
}
int GaugeArc::getScaleMajor()const
{
return this->scaleMajor;
}
int GaugeArc::getScaleMinor()const
{
return this->scaleMinor;
}
int GaugeArc::getStartAngle()const
{
return this->startAngle;
}
int GaugeArc::getEndAngle()const
{
return this->endAngle;
}
bool GaugeArc::getAnimation()const
{
return this->animation;
}
double GaugeArc::getAnimationStep()const
{
return this->animationStep;
}
QColor GaugeArc::getArcColor()const
{
return this->arcColor;
}
QColor GaugeArc::getScaleColor()const
{
return this->scaleColor;
}
QColor GaugeArc::getScaleNumColor()const
{
return this->scaleNumColor;
}
QColor GaugeArc::getPointerColor()const
{
return this->pointerColor;
}
QColor GaugeArc::getTextColor()const
{
return this->textColor;
}
GaugeArc::PointerStyle GaugeArc::getPointerStyle()const
{
return this->pointerStyle;
}
QSize GaugeArc::sizeHint()const
{
int width = this->width();
int height = this->height();
return QSize(qMin(width, height), qMin(width, height));
}
QSize GaugeArc::minimumSizeHint()const
{
int width = this->width();
int height = this->height();
return QSize(qMin(width, height), qMin(width, height));
}
void GaugeArc::setRange(double minValue, double maxValue)
{
this->minValue = minValue;
this->maxValue = maxValue;
}
void GaugeArc::setRange(int minValue, int maxValue)
{
this->minValue = minValue;
this->maxValue = maxValue;
}
//設置最大最小值
void GaugeArc::setMinValue(double minValue)
{
this->minValue = minValue;
}
void GaugeArc::setMaxValue(double maxValue)
{
this->maxValue = maxValue;
}
//設置目標值
void GaugeArc::setValue(double value)
{
this->value = value;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
else {
this->currentValue = this->value;
}
update();
}
void GaugeArc::setValue(int value)
{
this->value =value;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
else {
this->currentValue = this->value;
}
update();
}
//設置精確度
void GaugeArc::setPrecision(int precision)
{
this->precision = precision;
}
//設置主刻度數量
void GaugeArc::setScaleMajor(int scaleMajor)
{
this->scaleMajor = scaleMajor;
}
//設置小刻度數量
void GaugeArc::setScaleMinor(int scaleMinor)
{
this->scaleMinor = scaleMinor;
}
//設置開始旋轉角度
void GaugeArc::setStartAngle(int startAngle)
{
this->startAngle = startAngle;
}
//設置結束旋轉角度
void GaugeArc::setEndAngle(int endAngle)
{
this->endAngle = endAngle;
}
//設置是否啓用動畫顯示
void GaugeArc::setAnimation(bool animation)
{
this->animation = animation;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
}
//設置動畫顯示的步長
void GaugeArc::setAnimationStep(double animationStep)
{
this->animationStep = animationStep;
}
//設置圓弧顏色
void GaugeArc::setArcColor(const QColor &arcColor)
{
this->arcColor = arcColor;
}
//設置刻度尺顏色
void GaugeArc::setScaleColor(const QColor &scaleColor)
{
this->scaleColor = scaleColor;
}
//設置刻度值顏色
void GaugeArc::setScaleNumColor(const QColor &scaleNumColor)
{
this->scaleNumColor = scaleNumColor;
}
//設置指針顏色
void GaugeArc::setPointerColor(const QColor &pointerColor)
{
this->pointerColor = pointerColor;
}
//設置文本顏色
void GaugeArc::setTextColor(const QColor &textColor)
{
this->textColor = textColor;
}
//設置指針樣式
void GaugeArc::setPointerStyle(const PointerStyle &pointerStyle)
{
this->pointerStyle = pointerStyle;
}
void GaugeArc::updateValue()
{
if(this->animation == true)
{
if(fabs(currentValue - value) > 0.001)
{
if(currentValue - value > 0.001)
currentValue = currentValue - animationStep;
else {
currentValue = currentValue + animationStep;
}
QTimer::singleShot(5, this, SLOT(updateValue()));
update();
}
}
}
代碼下載地址:https://download.csdn.net/download/wang112031/12032937