#pragma execution_character_set("utf-8") #include "gaugepanel.h" #include "qpainter.h" #include #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(); } }