emsApplication/applications/examples/quc_demo/gaugepanel.cpp

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();
}
}