569 lines
11 KiB
C++
569 lines
11 KiB
C++
#pragma execution_character_set("utf-8")
|
|
|
|
#include "gaugepanel.h"
|
|
#include "qpainter.h"
|
|
#include <QPainterPath>
|
|
#include "qmath.h"
|
|
#include "qtimer.h"
|
|
#include "qlcdnumber.h"
|
|
#include "qdebug.h"
|
|
|
|
GaugePanel::GaugePanel(QWidget *parent) : QWidget(parent)
|
|
{
|
|
minValue = 0;
|
|
maxValue = 100;
|
|
value = 0;
|
|
precision = 0;
|
|
scalePrecision = 0;
|
|
|
|
scaleMajor = 10;
|
|
scaleMinor = 5;
|
|
startAngle = 45;
|
|
endAngle = 45;
|
|
|
|
animation = false;
|
|
animationStep = 0.5;
|
|
|
|
ringWidth = 10;
|
|
ringColor = QColor(54, 192, 254);
|
|
|
|
scaleColor = QColor(34, 163, 169);
|
|
pointerColor = QColor(34, 163, 169);
|
|
bgColor = Qt::transparent;
|
|
textColor = QColor(50, 50, 50);
|
|
unit = "V";
|
|
text = "电压";
|
|
|
|
reverse = false;
|
|
currentValue = 0;
|
|
timer = new QTimer(this);
|
|
timer->setInterval(10);
|
|
connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
|
|
|
|
//setFont(QFont("Arial", 9));
|
|
}
|
|
|
|
GaugePanel::~GaugePanel()
|
|
{
|
|
if (timer->isActive())
|
|
{
|
|
timer->stop();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::paintEvent(QPaintEvent *)
|
|
{
|
|
int width = this->width();
|
|
int height = this->height();
|
|
int side = qMin(width, height);
|
|
|
|
//绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
|
|
QPainter painter(this);
|
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
|
|
|
//绘制背景
|
|
if (bgColor != Qt::transparent)
|
|
{
|
|
painter.setPen(Qt::NoPen);
|
|
painter.fillRect(this->rect(), bgColor);
|
|
}
|
|
|
|
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 GaugePanel::drawRing(QPainter *painter)
|
|
{
|
|
int radius = 70;
|
|
painter->save();
|
|
|
|
QPen pen;
|
|
pen.setCapStyle(Qt::FlatCap);
|
|
pen.setWidthF(ringWidth);
|
|
pen.setColor(ringColor);
|
|
painter->setPen(pen);
|
|
|
|
radius = radius - ringWidth;
|
|
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
|
|
double angleAll = 360.0 - startAngle - endAngle;
|
|
painter->drawArc(rect, (270 - startAngle - angleAll) * 16, angleAll * 16);
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
void GaugePanel::drawScale(QPainter *painter)
|
|
{
|
|
int radius = 80;
|
|
painter->save();
|
|
|
|
painter->rotate(startAngle);
|
|
int steps = (scaleMajor * scaleMinor);
|
|
double angleStep = (360.0 - startAngle - endAngle) / steps;
|
|
|
|
QPen pen;
|
|
pen.setCapStyle(Qt::RoundCap);
|
|
pen.setColor(scaleColor);
|
|
|
|
for (int i = 0; i <= steps; i++)
|
|
{
|
|
if (i % scaleMinor == 0)
|
|
{
|
|
pen.setWidthF(1.5);
|
|
painter->setPen(pen);
|
|
painter->drawLine(0, radius - 8, 0, radius + 5);
|
|
}
|
|
else
|
|
{
|
|
pen.setWidthF(0.5);
|
|
painter->setPen(pen);
|
|
painter->drawLine(0, radius - 8, 0, radius - 3);
|
|
}
|
|
|
|
painter->rotate(angleStep);
|
|
}
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
void GaugePanel::drawScaleNum(QPainter *painter)
|
|
{
|
|
int radius = 95;
|
|
painter->save();
|
|
painter->setPen(scaleColor);
|
|
|
|
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', scalePrecision);
|
|
double textWidth = fontMetrics().size(Qt::TextSingleLine,strValue).width();// .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 GaugePanel::drawPointer(QPainter *painter)
|
|
{
|
|
int radius = 70;
|
|
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);
|
|
double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
|
|
painter->rotate(degRotate);
|
|
painter->drawConvexPolygon(pts);
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
void GaugePanel::drawValue(QPainter *painter)
|
|
{
|
|
int radius = 100;
|
|
painter->save();
|
|
painter->setPen(textColor);
|
|
|
|
QFont font;
|
|
font.setPixelSize(15);
|
|
painter->setFont(font);
|
|
|
|
QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
|
|
strValue = QString("%1 %2").arg(strValue).arg(unit);
|
|
QRectF valueRect(-radius, radius / 3.5, radius * 2, radius / 3.5);
|
|
painter->drawText(valueRect, Qt::AlignCenter, strValue);
|
|
|
|
QRectF textRect(-radius, radius / 2.5, radius * 2, radius / 2.5);
|
|
font.setPixelSize(12);
|
|
painter->setFont(font);
|
|
painter->drawText(textRect, Qt::AlignCenter, text);
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
void GaugePanel::updateValue()
|
|
{
|
|
if (!reverse)
|
|
{
|
|
if (currentValue >= value)
|
|
{
|
|
timer->stop();
|
|
}
|
|
else
|
|
{
|
|
currentValue += animationStep;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (currentValue <= value)
|
|
{
|
|
timer->stop();
|
|
}
|
|
else
|
|
{
|
|
currentValue -= animationStep;
|
|
}
|
|
}
|
|
|
|
this->update();
|
|
}
|
|
|
|
double GaugePanel::getMinValue() const
|
|
{
|
|
return this->minValue;
|
|
}
|
|
|
|
double GaugePanel::getMaxValue() const
|
|
{
|
|
return this->maxValue;
|
|
}
|
|
|
|
double GaugePanel::getValue() const
|
|
{
|
|
return this->value;
|
|
}
|
|
|
|
int GaugePanel::getPrecision() const
|
|
{
|
|
return this->precision;
|
|
}
|
|
|
|
int GaugePanel::getScalePrecision() const
|
|
{
|
|
return this->scalePrecision;
|
|
}
|
|
|
|
int GaugePanel::getScaleMajor() const
|
|
{
|
|
return this->scaleMajor;
|
|
}
|
|
|
|
int GaugePanel::getScaleMinor() const
|
|
{
|
|
return this->scaleMinor;
|
|
}
|
|
|
|
int GaugePanel::getStartAngle() const
|
|
{
|
|
return this->startAngle;
|
|
}
|
|
|
|
int GaugePanel::getEndAngle() const
|
|
{
|
|
return this->endAngle;
|
|
}
|
|
|
|
bool GaugePanel::getAnimation() const
|
|
{
|
|
return this->animation;
|
|
}
|
|
|
|
double GaugePanel::getAnimationStep() const
|
|
{
|
|
return this->animationStep;
|
|
}
|
|
|
|
int GaugePanel::getRingWidth() const
|
|
{
|
|
return this->ringWidth;
|
|
}
|
|
|
|
QColor GaugePanel::getRingColor() const
|
|
{
|
|
return this->ringColor;
|
|
}
|
|
|
|
QColor GaugePanel::getScaleColor() const
|
|
{
|
|
return this->scaleColor;
|
|
}
|
|
|
|
QColor GaugePanel::getPointerColor() const
|
|
{
|
|
return this->pointerColor;
|
|
}
|
|
|
|
QColor GaugePanel::getBgColor() const
|
|
{
|
|
return this->bgColor;
|
|
}
|
|
|
|
QColor GaugePanel::getTextColor() const
|
|
{
|
|
return this->textColor;
|
|
}
|
|
|
|
QString GaugePanel::getUnit() const
|
|
{
|
|
return this->unit;
|
|
}
|
|
|
|
QString GaugePanel::getText() const
|
|
{
|
|
return this->text;
|
|
}
|
|
|
|
QSize GaugePanel::sizeHint() const
|
|
{
|
|
return QSize(200, 200);
|
|
}
|
|
|
|
QSize GaugePanel::minimumSizeHint() const
|
|
{
|
|
return QSize(50, 50);
|
|
}
|
|
|
|
void GaugePanel::setRange(double minValue, double maxValue)
|
|
{
|
|
//如果最小值大于或者等于最大值则不设置
|
|
if (minValue >= maxValue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->minValue = minValue;
|
|
this->maxValue = maxValue;
|
|
|
|
//如果目标值不在范围值内,则重新设置目标值
|
|
if (value < minValue || value > maxValue)
|
|
{
|
|
setValue(value);
|
|
}
|
|
|
|
this->update();
|
|
}
|
|
|
|
void GaugePanel::setRange(int minValue, int maxValue)
|
|
{
|
|
setRange((double)minValue, (double)maxValue);
|
|
}
|
|
|
|
void GaugePanel::setMinValue(double minValue)
|
|
{
|
|
setRange(minValue, maxValue);
|
|
}
|
|
|
|
void GaugePanel::setMaxValue(double maxValue)
|
|
{
|
|
setRange(minValue, maxValue);
|
|
}
|
|
|
|
void GaugePanel::setValue(double value)
|
|
{
|
|
//值和当前值一致则无需处理
|
|
if (value == this->value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//值小于最小值则取最小值,大于最大值则取最大值
|
|
if (value < minValue)
|
|
{
|
|
value = minValue;
|
|
}
|
|
else if (value > maxValue)
|
|
{
|
|
value = maxValue;
|
|
}
|
|
|
|
if (value > this->value)
|
|
{
|
|
reverse = false;
|
|
}
|
|
else if (value < this->value)
|
|
{
|
|
reverse = true;
|
|
}
|
|
|
|
this->value = value;
|
|
emit valueChanged(value);
|
|
|
|
if (!animation)
|
|
{
|
|
currentValue = this->value;
|
|
this->update();
|
|
}
|
|
else
|
|
{
|
|
timer->start();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setValue(int value)
|
|
{
|
|
setValue((double)value);
|
|
}
|
|
|
|
void GaugePanel::setPrecision(int precision)
|
|
{
|
|
//最大精确度为 3
|
|
if (precision <= 3 && this->precision != precision)
|
|
{
|
|
this->precision = precision;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setScalePrecision(int scalePrecision)
|
|
{
|
|
//最大精确度为 2
|
|
if (scalePrecision <= 2 && this->scalePrecision != scalePrecision)
|
|
{
|
|
this->scalePrecision = scalePrecision;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setScaleMajor(int scaleMajor)
|
|
{
|
|
if (this->scaleMajor != scaleMajor)
|
|
{
|
|
this->scaleMajor = scaleMajor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setScaleMinor(int scaleMinor)
|
|
{
|
|
if (this->scaleMinor != scaleMinor)
|
|
{
|
|
this->scaleMinor = scaleMinor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setStartAngle(int startAngle)
|
|
{
|
|
if (this->startAngle != startAngle)
|
|
{
|
|
this->startAngle = startAngle;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setEndAngle(int endAngle)
|
|
{
|
|
if (this->endAngle != endAngle)
|
|
{
|
|
this->endAngle = endAngle;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setAnimation(bool animation)
|
|
{
|
|
if (this->animation != animation)
|
|
{
|
|
this->animation = animation;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setAnimationStep(double animationStep)
|
|
{
|
|
if (this->animationStep != animationStep)
|
|
{
|
|
this->animationStep = animationStep;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setRingWidth(int ringWidth)
|
|
{
|
|
if (this->ringWidth != ringWidth)
|
|
{
|
|
this->ringWidth = ringWidth;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setRingColor(const QColor &ringColor)
|
|
{
|
|
if (this->ringColor != ringColor)
|
|
{
|
|
this->ringColor = ringColor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setScaleColor(const QColor &scaleColor)
|
|
{
|
|
if (this->scaleColor != scaleColor)
|
|
{
|
|
this->scaleColor = scaleColor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setPointerColor(const QColor &pointerColor)
|
|
{
|
|
if (this->pointerColor != pointerColor)
|
|
{
|
|
this->pointerColor = pointerColor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setBgColor(const QColor &bgColor)
|
|
{
|
|
if (this->bgColor != bgColor)
|
|
{
|
|
this->bgColor = bgColor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setTextColor(const QColor &textColor)
|
|
{
|
|
if (this->textColor != textColor)
|
|
{
|
|
this->textColor = textColor;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setUnit(const QString &unit)
|
|
{
|
|
if (this->unit != unit)
|
|
{
|
|
this->unit = unit;
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void GaugePanel::setText(const QString &text)
|
|
{
|
|
if (this->text != text)
|
|
{
|
|
this->text = text;
|
|
this->update();
|
|
}
|
|
}
|