核心代码来自 feiyangqingyun 大神链接:https://blog.csdn.net/feiyangqingyun/article/details/89428878
#ifndef DASHBOARD_H
#define DASHBOARD_H
#include <QWidget>
#include <QColor>
#include <QTimer>
#include <QFont>
class QLCDNumber;
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif
class QDESIGNER_WIDGET_EXPORT GaugeSpeed : public QWidget
#else
class Dashboard : public QWidget
#endif
{
Q_OBJECT
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(int ringWidth READ getRingWidth WRITE setRingWidth)
Q_PROPERTY(int ringStartPercent READ getRingStartPercent WRITE setRingStartPercent)
Q_PROPERTY(int ringMidPercent READ getRingMidPercent WRITE setRingMidPercent)
Q_PROPERTY(int ringEndPercent READ getRingEndPercent WRITE setRingEndPercent)
Q_PROPERTY(QColor ringColorStart READ getRingColorStart WRITE setRingColorStart)
Q_PROPERTY(QColor ringColorMid READ getRingColorMid WRITE setRingColorMid)
Q_PROPERTY(QColor ringColorEnd READ getRingColorEnd WRITE setRingColorEnd)
Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
public:
explicit Dashboard(QWidget *parent = 0);
~Dashboard();
protected:
//void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
void drawRing(QPainter *painter);
void drawScale(QPainter *painter);
void drawScaleNum(QPainter *painter);
void drawPointer(QPainter *painter);
void drawValue(QPainter *painter);
private slots:
void updateValue();
private:
double minValue = -5; //最小值
double maxValue = 5; //最大值
double value = 0; //目标值
int precision = 2; //精确度,小数点后几位
int scaleMajor = 10; //大刻度数量
int scaleMinor = 5; //小刻度数量
int startAngle = 45; //开始旋转角度
int endAngle = 45; //结束旋转角度
bool animation = 0; //是否启用动画显示
double animationStep = 1; //动画显示时步长
int ringWidth = 7; //圆环宽度
int ringStartPercent=10; //第一圆环比例
int ringMidLeftPercent=10;
int ringMidPercent=60; //第二圆环比例
int ringMidRightPercent=10;
int ringEndPercent=10; //第三圆环比例
QColor ringColorStart= QColor(255,0,0,255); //第一圆环颜色
QColor ringColorMidLeft = QColor(250,211,0,144);
QColor ringColorMid = QColor(0,255,0,255); //第二圆环颜色
QColor ringColorMidRight = QColor(250,211,0,144);
QColor ringColorEnd = QColor(255,0,0,255); //第三圆环颜色
QColor pointerColor = Qt::red; //指针颜色
QColor textColor = Qt::red;//Qt::darkGreen; //文字颜色
bool reverse; //是否往回走
double currentValue = 0; //当前值
QTimer *timer; //定时器绘制动画
QLCDNumber *lcd; //数码管
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;
int getRingWidth() const;
int getRingStartPercent() const;
int getRingMidPercent() const;
int getRingEndPercent() const;
QColor getRingColorStart() const;
QColor getRingColorMid() const;
QColor getRingColorEnd() const;
QColor getPointerColor() const;
QColor getTextColor() 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 setValue(const QString &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 setRingWidth(int ringWidth);
//设置三个圆环所占比例
void setRingStartPercent(int ringStartPercent);
void setRingMidPercent(int ringMidPercent);
void setRingEndPercent(int ringEndPercent);
//设置三个圆环颜色
void setRingColorStart(const QColor &ringColorStart);
void setRingColorMid(const QColor &ringColorMid);
void setRingColorEnd(const QColor &ringColorEnd);
//设置指针颜色
void setPointerColor(const QColor &pointerColor);
//设置文本颜色
void setTextColor(const QColor &textColor);
Q_SIGNALS:
void valueChanged(int value);
};
#endif // DASHBOARD_H
#include "dashboard.h"
#include <QPainter>
#include <QDebug>
#include <QtMath>
Dashboard::Dashboard(QWidget *parent) : QWidget(parent)
{
if(this->animation == true)
{
QTimer::singleShot(50, this, SLOT(updateValue()));
}
}
Dashboard::~Dashboard()
{
}
void Dashboard::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); /* 比例缩放 */
drawRing(&painter);
drawScale(&painter);
drawScaleNum(&painter);
drawPointer(&painter);
drawValue(&painter);
}
void Dashboard::drawRing(QPainter *painter)
{
int radius = 100;
painter->save();
QPen pen;
pen.setCapStyle(Qt::FlatCap);
pen.setWidthF(ringWidth);
radius = radius - ringWidth;
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
//计算总范围角度,根据占比例自动计算三色圆环范围角度
double angleAll = 360.0 - startAngle - endAngle;
double angleStart = angleAll * (double)ringStartPercent / 100;
double angleMidLeft = angleAll * (double)ringMidLeftPercent / 100;
double angleMid = angleAll * (double)ringMidPercent / 100;
double angleMidRight = angleAll * (double)ringMidRightPercent / 100;
double angleEnd = angleAll * (double)ringEndPercent / 100;
//绘制第一圆环
pen.setColor(ringColorStart);
painter->setPen(pen);
painter->drawArc(rect, (270 - startAngle - angleStart) * 16, angleStart * 16);
pen.setColor(ringColorMidLeft);
painter->setPen(pen);
painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft) * 16, angleMidLeft * 16);
//绘制第二圆环
pen.setColor(ringColorMid);
painter->setPen(pen);
painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft- angleMid) * 16, angleMid * 16);
pen.setColor(ringColorMidRight);
painter->setPen(pen);
painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft- angleMid - angleMidRight) * 16, angleMidRight * 16);
//绘制第三圆环
pen.setColor(ringColorEnd);
painter->setPen(pen);
painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft - angleMid -angleMidRight - angleEnd) * 16, angleEnd * 16);
painter->restore();
}
void Dashboard::drawScale(QPainter *painter)
{
int radius = 94;
painter->save();
QPen pen;
pen.setColor(textColor);
pen.setCapStyle(Qt::RoundCap);
painter->rotate(startAngle);
int steps = (scaleMajor * scaleMinor);
double angleStep = (360.0 - startAngle - endAngle) / steps;
//计算圆环对应大刻度范围索引
int indexStart = steps * (double)ringStartPercent / 100 + 1;
int indexMidLeft = steps * (double)ringMidLeftPercent / 100 - 1;
int indexMid = steps * (double)ringMidPercent / 100 - 1;
int indexMidRight = steps * (double)ringMidRightPercent / 100 - 1;
int indexEnd = steps * (double)ringEndPercent / 100 + 1;
int index = 0;
//qDebug("drawScale index=%d indexStart=%d", index, indexStart);
for (int i = 0; i <= steps; i++) {
//if (i % scaleMinor == 0) {
//根据所在圆环范围切换颜色
if (index < indexStart) {
pen.setColor(ringColorStart);
} else if (index < (indexStart + indexMidLeft+1)) {
pen.setColor(ringColorMidLeft);
}
else if (index < (indexStart + indexMid + indexMidLeft+1)) {
pen.setColor(ringColorMid);
}
else if (index <= (indexStart + indexMid + indexMidLeft + indexMidRight + 1)) {
pen.setColor(ringColorMidRight);
}
else if (index < (indexStart + indexMid + indexMidLeft + indexMidRight + indexEnd)) {
pen.setColor(ringColorEnd);
}
index++;
if (i % scaleMinor == 0){
pen.setWidthF(0.5); //1.5
painter->setPen(pen);
painter->drawLine(0, radius - 5 - ringWidth, 0, radius - ringWidth+1);
} else {
pen.setWidthF(0.5);
painter->setPen(pen);
painter->drawLine(0, radius - 3 - ringWidth, 0, radius - ringWidth+1);
}
painter->rotate(angleStep);
}
painter->restore();
}
void Dashboard::drawScaleNum(QPainter *painter)
{
int radius = 70;
painter->save();
painter->setPen(textColor);
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;
if(value >= -3.00 && value <= 3.00)
painter->setPen(ringColorMid);
else {
painter->setPen(textColor);
}
QString strValue = QString("%1").arg((double)value, 0, 'f', 0);
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 Dashboard::drawPointer(QPainter *painter)
{
int radius = 62;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(pointerColor);
QPolygon pts;
pts.setPoints(4, -5, 0, 0, -8, 5, 0, 0, radius);
painter->rotate(startAngle);
if(maxValue < currentValue)
currentValue = maxValue;
else if(minValue > currentValue)
currentValue = minValue;
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
painter->rotate(degRotate);
painter->drawConvexPolygon(pts);
painter->restore();
}
void Dashboard::drawValue(QPainter *painter)
{
int radius = 100;
painter->save();
painter->setPen(textColor);
//painter->setBrush(QColor(255,0,0,255));
QFont font;
font.setPixelSize(12);
font.setFamily("微软雅黑");
painter->setFont(font);
// QRectF textRect(-radius, radius / 2, radius * 2, radius / 3);
QRectF textRect(-radius/4, radius / 4, radius/4*2, radius / 4);
painter->drawRect(textRect); //增加一个矩形框
painter->setPen(Qt::black);
QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
painter->drawText(textRect, Qt::AlignCenter, strValue);
painter->setPen(textColor);
QRectF text(-radius/2, -radius / 2, radius, radius / 4);
//painter->drawRect(text); //增加一个矩形框
QString textValue="差分张力(KN)";
painter->drawText(text, Qt::AlignCenter, textValue);
painter->restore();
}
double Dashboard::getMinValue()const
{
return this->minValue;
}
double Dashboard::getMaxValue()const
{
return this->maxValue;
}
double Dashboard::getValue()const
{
return this->currentValue;
}
int Dashboard::getPrecision()const
{
return this->precision;
}
int Dashboard::getScaleMajor()const
{
return this->scaleMajor;
}
int Dashboard::getScaleMinor()const
{
return this->scaleMinor;
}
int Dashboard::getStartAngle()const
{
return this->startAngle;
}
int Dashboard::getEndAngle()const
{
return this->endAngle;
}
bool Dashboard::getAnimation()const
{
return this->animation;
}
double Dashboard::getAnimationStep()const
{
return this->animationStep;
}
int Dashboard::getRingWidth()const
{
return this->ringWidth;
}
int Dashboard::getRingStartPercent()const
{
return this->ringStartPercent;
}
int Dashboard::getRingMidPercent()const
{
return this->ringMidPercent;
}
int Dashboard::getRingEndPercent()const
{
return this->ringEndPercent;
}
QColor Dashboard::getRingColorStart() const
{
return this->ringColorStart;
}
QColor Dashboard::getRingColorMid() const
{
return this->ringColorMid;
}
QColor Dashboard::getRingColorEnd() const
{
return this->ringColorEnd;
}
QColor Dashboard::getPointerColor() const
{
return this->pointerColor;
}
QColor Dashboard::getTextColor() const
{
return this->textColor;
}
QSize Dashboard::sizeHint()const
{
int width = this->width();
int height = this->height();
return QSize(qMin(width, height), qMin(width, height));
}
QSize Dashboard::minimumSizeHint()const
{
int width = this->width();
int height = this->height();
return QSize(qMin(width, height), qMin(width, height));
}
void Dashboard::setRange(double minValue, double maxValue)
{
this->minValue = minValue;
this->maxValue = maxValue;
}
void Dashboard::setRange(int minValue, int maxValue)
{
this->minValue = minValue;
this->maxValue = maxValue;
}
//设置最大最小值
void Dashboard::setMinValue(double minValue)
{
this->minValue = minValue;
}
void Dashboard::setMaxValue(double maxValue)
{
this->maxValue = maxValue;
}
//设置目标值
void Dashboard::setValue(double value)
{
this->value = value;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
else {
this->currentValue = this->value;
}
update();
}
void Dashboard::setValue(int value)
{
this->value =value;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
else {
this->currentValue = this->value;
}
update();
}
void Dashboard::setValue(const QString &value)
{
this->value = value.toDouble();
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
else {
this->currentValue = this->value;
}
update();
}
//设置精确度
void Dashboard::setPrecision(int precision)
{
this->precision = precision;
}
//设置主刻度数量
void Dashboard::setScaleMajor(int scaleMajor)
{
this->scaleMajor = scaleMajor;
}
//设置小刻度数量
void Dashboard::setScaleMinor(int scaleMinor)
{
this->scaleMinor = scaleMinor;
}
//设置开始旋转角度
void Dashboard::setStartAngle(int startAngle)
{
this->startAngle = startAngle;
}
//设置结束旋转角度
void Dashboard::setEndAngle(int endAngle)
{
this->endAngle = endAngle;
}
//设置是否启用动画显示
void Dashboard::setAnimation(bool animation)
{
this->animation = animation;
if(this->animation == true)
{
QTimer::singleShot(5, this, SLOT(updateValue()));
}
}
//设置动画显示的步长
void Dashboard::setAnimationStep(double animationStep)
{
this->animationStep = animationStep;
}
void Dashboard::setRingWidth(int ringWidth)
{
this->ringWidth = ringWidth;
}
//设置三个圆环所占比例
void Dashboard::setRingStartPercent(int ringStartPercent)
{
this->ringStartPercent = ringStartPercent;
}
void Dashboard::setRingMidPercent(int ringMidPercent)
{
this->ringMidPercent = ringMidPercent;
}
void Dashboard::setRingEndPercent(int ringEndPercent)
{
this->ringEndPercent = ringEndPercent;
}
//设置三个圆环颜色
void Dashboard::setRingColorStart(const QColor &ringColorStart)
{
this->ringColorStart = ringColorStart;
}
void Dashboard::setRingColorMid(const QColor &ringColorMid)
{
this->ringColorMid = ringColorMid;
}
void Dashboard::setRingColorEnd(const QColor &ringColorEnd)
{
this->ringColorEnd = ringColorEnd;
}
//设置指针颜色
void Dashboard::setPointerColor(const QColor &pointerColor)
{
this->pointerColor = pointerColor;
}
//设置文本颜色
void Dashboard::setTextColor(const QColor &textColor)
{
this->textColor = textColor;
}
void Dashboard::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();
}
}
}