1. 预览图
2. 代码
头文件
#ifndef GAUGEPANEL_H
#define GAUGEPANEL_H
#include <QWidget>
#include <QPropertyAnimation>
#include <QtMath>
#include <QPainter>
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif
class QDESIGNER_WIDGET_EXPORT GaugePanel : public QWidget
#else
class GaugePanel : public QWidget
#endif
{
Q_OBJECT
Q_PROPERTY(double value READ getValue WRITE setValue)
Q_PROPERTY(int hShearValue READ getHShearValue WRITE setHShearValue)
Q_PROPERTY(int vShearValue READ getVShearValue WRITE setVShearValue)
Q_PROPERTY(double radiusInner READ getRadiusInner WRITE setRadiusInner)
Q_PROPERTY(double radiusOuter READ getRadiusOuter WRITE setRadiusOuter)
Q_PROPERTY(double radiusHalo READ getRadiusHalo WRITE setRadiusHalo)
Q_PROPERTY(QColor colorOuterFrame READ getColorOuterFrame WRITE setColorOuterFrame)
Q_PROPERTY(QColor colorInnerStart READ getColorInnerStart WRITE setColorInnerStart)
Q_PROPERTY(QColor colorInnerEnd READ getColorInnerEnd WRITE setColorInnerEnd)
Q_PROPERTY(QColor colorOuterStart READ getColorOuterStart WRITE setColorOuterStart)
Q_PROPERTY(QColor colorOuterEnd READ getColorOuterEnd WRITE setColorOuterEnd)
Q_PROPERTY(QColor colorHaloStart READ getColorHaloStart WRITE setColorHaloStart)
Q_PROPERTY(QColor colorHaloEnd READ getColorHaloEnd WRITE setColorHaloEnd)
public:
explicit GaugePanel(QWidget *parent = nullptr);
~GaugePanel();
protected:
void paintEvent(QPaintEvent *);
private:
void drawOuterGradient(QPainter *painter);
void drawInnerGradient(QPainter *painter);
void drawOuterHalo(QPainter *painter);
void drawScale(QPainter *painter);
void drawScaleNum(QPainter *painter);
void drawPointer(QPainter *painter);
void drawPointerSector(QPainter *painter);
void drawValue(QPainter *painter);
void drawUnit(QPainter *painter);
private:
double value; //目标值
int hShearValue, vShearValue;//H、V扭曲值
double radiusInner; //渐变内圈内半径
double radiusOuter; //渐变外圈内半径
double radiusHalo; //光晕内半径
QColor colorOuterFrame; //表盘外边框颜色
QColor colorInnerStart; //渐变内圈起始颜色
QColor colorInnerEnd; //渐变内圈结束颜色
QColor colorOuterStart; //渐变外圈起始颜色
QColor colorOuterEnd; //渐变外圈结束颜色
QColor colorHaloStart; //光晕起始颜色
QColor colorHaloEnd; //光晕结束颜色
QPropertyAnimation *hShearAnimation, *vShearAnimation;
public:
double getValue() const;
int getHShearValue() const;
int getVShearValue() const;
double getRadiusInner() const;
double getRadiusOuter() const;
double getRadiusHalo() const;
QColor getColorOuterFrame() const;
QColor getColorInnerStart() const;
QColor getColorInnerEnd() const;
QColor getColorOuterStart() const;
QColor getColorOuterEnd() const;
QColor getColorHaloStart() const;
QColor getColorHaloEnd() const;
void setValue(int value);
void setValue(double value);
void setHShearValue(int value);
void setVShearValue(int value);
//表盘外边框颜色
void setColorOuterFrame(QColor color);
//内层渐变区半径
void setRadiusInner(int radius);
void setRadiusInner(double radius);
//外层渐变区半径
void setRadiusOuter(int radius);
void setRadiusOuter(double radius);
//外层光晕区半径
void setRadiusHalo(int radius);
void setRadiusHalo(double radius);
//内层渐变颜色
void setColorInnerStart(QColor color);
void setColorInnerEnd(QColor color);
//外层渐变颜色
void setColorOuterStart(QColor color);
void setColorOuterEnd(QColor color);
//光晕颜色
void setColorHaloStart(QColor color);
void setColorHaloEnd(QColor color);
void startShearAnimal(int duration, int hShearValue, int vShearValue);
public slots:
void updateValue(double value);
Q_SIGNALS:
void valueChanged(qreal value);
};
#endif // GaugePanel_H
源文件
#include "gaugepanel.h"
GaugePanel::GaugePanel(QWidget *parent) : QWidget(parent)
{
value = hShearValue = vShearValue = 0.0;
radiusInner = 65.0;
radiusOuter = 76.25;
radiusHalo = 87.5;
colorOuterFrame = QColor(50, 154, 255, 250);
colorInnerStart = QColor(50, 154, 255, 180);
colorInnerEnd = QColor(50, 154, 255, 70);
colorOuterStart = QColor(50, 154, 255, 150);
colorOuterEnd = QColor(50, 154, 255, 200);
colorHaloStart = QColor(100, 180, 255, 80);
colorHaloEnd = QColor(30, 80, 120, 20);
hShearAnimation = new QPropertyAnimation(this, "hShearValue");
vShearAnimation = new QPropertyAnimation(this, "vShearValue");
}
GaugePanel::~GaugePanel()
{
hShearAnimation->stop();
vShearAnimation->stop();
delete hShearAnimation;
delete vShearAnimation;
}
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);
painter.translate(width / 2, height / 2);
painter.scale(side / 215.0, side / 215.0);
painter.shear(double(hShearValue/100.0f), double(vShearValue/100.0f));
//内层渐变
drawInnerGradient(&painter);
//外层渐变
drawOuterGradient(&painter);
//外层光晕
drawOuterHalo(&painter);
//刻度线
drawScale(&painter);
//刻度值
drawScaleNum(&painter);
//绘制指针
drawPointer(&painter);
//绘制指针扇形
drawPointerSector(&painter);
//绘制值
drawValue(&painter);
//绘制单位
drawUnit(&painter);
}
void GaugePanel::drawOuterGradient(QPainter *painter)
{
if(radiusHalo <= radiusOuter)
return;
painter->save();
QRectF rectangle(0-radiusHalo, 0-radiusHalo, radiusHalo*2, radiusHalo*2);
QPen framePen(colorOuterFrame);
framePen.setWidthF(1.5f);
painter->setPen(framePen);
painter->drawEllipse(rectangle);
painter->setPen(Qt::NoPen);
QPainterPath smallCircle;
QPainterPath bigCircle;
float radius = radiusOuter;
smallCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
radius += (radiusHalo - radiusOuter);
bigCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
//大圆抛去小圆部分
QPainterPath gradientPath = bigCircle - smallCircle;
QRadialGradient gradient(0, 0, radius, 0, 0);
//gradient.setSpread(QGradient::ReflectSpread);
gradient.setColorAt(0.85, colorOuterStart);
gradient.setColorAt(0.98, colorOuterEnd);
painter->setBrush(gradient);
painter->drawPath(gradientPath);
painter->restore();
}
void GaugePanel::drawInnerGradient(QPainter *painter)
{
if(radiusOuter <= radiusInner)
return;
painter->save();
painter->setPen(Qt::NoPen);
QPainterPath smallCircle;
QPainterPath bigCircle;
float radius = radiusInner;
smallCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
radius += (radiusOuter - radiusInner);
bigCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
//大圆抛去小圆部分
QPainterPath gradientPath = bigCircle - smallCircle;
QRadialGradient gradient(0, 0, radius, 0, 0);
//gradient.setSpread(QGradient::ReflectSpread);
gradient.setColorAt(0.7, colorInnerStart);
gradient.setColorAt(1, colorInnerEnd);
painter->setBrush(gradient);
painter->drawPath(gradientPath);
painter->restore();
}
void GaugePanel::drawOuterHalo(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
QPainterPath smallCircle;
QPainterPath bigCircle;
float radius = radiusHalo;
smallCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
radius += (100.0 - radiusHalo);
bigCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
//大圆抛去小圆部分
QPainterPath gradientPath = bigCircle - smallCircle;
QRadialGradient gradient(0, 0, 100, 0, 0);
gradient.setSpread(QGradient::ReflectSpread);
gradient.setColorAt(radiusHalo/100, colorHaloStart);
gradient.setColorAt(1, colorHaloEnd);
painter->setBrush(gradient);
painter->drawPath(gradientPath);
painter->restore();
}
void GaugePanel::drawScale(QPainter *painter)
{
float radius = 85;
painter->save();
painter->setPen(QColor(255, 255, 255));
painter->rotate(30);
int steps = (30);
double angleStep = (360.0 - 60) / steps;
QPen pen = painter->pen();
pen.setCapStyle(Qt::RoundCap);
for (int i = 0; i <= steps; i++) {
if (i % 3 == 0) {
pen.setWidthF(1.5);
painter->setPen(pen);
QLineF line(0.0f, radius - 8.0f, 0.0f, radius);
painter->drawLine(line);
} else {
pen.setWidthF(0.5);
painter->setPen(pen);
QLineF line(0.0f, radius - 3.0f, 0.0f, radius);
painter->drawLine(line);
}
painter->rotate(angleStep);
}
painter->restore();
}
void GaugePanel::drawScaleNum(QPainter *painter)
{
float radius = 95.0f;
painter->save();
painter->setPen(QColor(255, 255, 255));
double startRad = (330 - 90) * (M_PI / 180);
double deltaRad = (300) * (M_PI / 180) / 10;
for (int i = 0; i <= 10; i++) {
double sina = sin(startRad - i * deltaRad);
double cosa = cos(startRad - i * deltaRad);
double value = 1.0 * i * ((30) / 10);//刻度值范围
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 GaugePanel::drawPointer(QPainter *painter)
{
painter->save();
float radius = 83.0;
painter->rotate(30+int(value*10));
QPen pen = painter->pen();
pen.setWidthF(1.0);
pen.setColor(QColor(50, 154, 255, 200));
painter->setPen(pen);
QLineF line(0.0f, 0.0f, 0.0f, radius);
painter->drawLine(line);
painter->restore();
}
void GaugePanel::drawPointerSector(QPainter *painter)
{
float radius = 87.5f;
painter->save();
painter->setPen(Qt::NoPen);
QRectF rect(-radius, -radius, radius * 2, radius * 2);
painter->setBrush(QColor(50, 154, 255, 50));
painter->drawPie(rect, -120*16, -value*16*10);
painter->restore();
}
void GaugePanel::drawValue(QPainter *painter)
{
int radius = 100;
painter->save();
painter->setPen(QColor(255, 255, 255));
painter->setFont(QFont("Arial", 22, 22, true));
QRectF textRect(-radius, -radius, radius * 2, radius * 2);
QString strValue = QString("%1").arg((double)value, 0, 'f', 0);
painter->drawText(textRect, Qt::AlignCenter, strValue);
painter->restore();
}
void GaugePanel::drawUnit(QPainter *painter)
{
int radius = 100;
painter->save();
painter->setPen(QColor(255, 255, 255));
painter->setFont(QFont("Arial", 9, -1, true));
QRectF textRect(-radius, -radius+20, radius * 2, radius * 2);
painter->drawText(textRect, Qt::AlignCenter, "km/h");
painter->restore();
}
double GaugePanel::getValue() const
{
return this->value;
}
int GaugePanel::getHShearValue() const
{
return this->hShearValue;
}
int GaugePanel::getVShearValue() const
{
return this->vShearValue;
}
double GaugePanel::getRadiusInner() const
{
return radiusInner;
}
double GaugePanel::getRadiusOuter() const
{
return radiusOuter;
}
double GaugePanel::getRadiusHalo() const
{
return radiusHalo;
}
QColor GaugePanel::getColorOuterFrame() const
{
return colorOuterFrame;
}
QColor GaugePanel::getColorInnerStart() const
{
return colorInnerStart;
}
QColor GaugePanel::getColorInnerEnd() const
{
return colorInnerEnd;
}
QColor GaugePanel::getColorOuterStart() const
{
return colorOuterStart;
}
QColor GaugePanel::getColorOuterEnd() const
{
return colorOuterEnd;
}
QColor GaugePanel::getColorHaloStart() const
{
return colorHaloStart;
}
QColor GaugePanel::getColorHaloEnd() const
{
return colorHaloEnd;
}
void GaugePanel::setValue(int value)
{
setValue(double(value));
}
void GaugePanel::setValue(double value) {
updateValue(value);
}
void GaugePanel::setHShearValue(int value)
{
if(value > 100 || value < -100)
return;
this->hShearValue = value;
update();
}
void GaugePanel::setVShearValue(int value)
{
if(value > 100 || value < -100)
return;
this->vShearValue = value;
update();
}
void GaugePanel::setColorOuterFrame(QColor color)
{
colorOuterFrame = color;
}
void GaugePanel::setRadiusInner(int radius)
{
setRadiusInner(double(radius));
}
void GaugePanel::setRadiusInner(double radius)
{
if(radius >= 0.0f && radius < 100.0f){
radiusInner = radius;
update();
}
}
void GaugePanel::setRadiusOuter(int radius)
{
setRadiusOuter(double(radius));
}
void GaugePanel::setRadiusOuter(double radius)
{
if(radius > 0.0f && radius < 100.0f){
radiusOuter = radius;
update();
}
}
void GaugePanel::setRadiusHalo(int radius)
{
setRadiusHalo(double(radius));
}
void GaugePanel::setRadiusHalo(double radius)
{
if(radius > 0.0f && radius < 100.0f){
radiusHalo = radius;
update();
}
}
void GaugePanel::setColorInnerStart(QColor color)
{
colorInnerStart = color;
}
void GaugePanel::setColorInnerEnd(QColor color)
{
colorInnerEnd = color;
}
void GaugePanel::setColorOuterStart(QColor color)
{
colorOuterStart = color;
}
void GaugePanel::setColorOuterEnd(QColor color)
{
colorOuterEnd = color;
}
void GaugePanel::setColorHaloStart(QColor color)
{
colorHaloStart = color;
}
void GaugePanel::setColorHaloEnd(QColor color)
{
colorHaloEnd = color;
}
void GaugePanel::startShearAnimal(int duration, int hShearValue, int vShearValue)
{
if(hShearValue == this->hShearValue && vShearValue == this->vShearValue){
return;
}
if(hShearAnimation->state() != QPropertyAnimation::Stopped){
hShearAnimation->stop();
}
if(vShearAnimation->state() != QPropertyAnimation::Stopped){
vShearAnimation->stop();
}
hShearAnimation->setDuration(duration);
hShearAnimation->setStartValue(this->hShearValue);
hShearAnimation->setEndValue(hShearValue);
hShearAnimation->start();
vShearAnimation->setDuration(duration);
vShearAnimation->setStartValue(this->vShearValue);
vShearAnimation->setEndValue(vShearValue);
vShearAnimation->start();
}
void GaugePanel::updateValue(double value)
{
if(value > 30.0 || value < 0.0){
return;
}
this->value = value;
//update();
this->update();
// emit valueChanged(value);
}
3. 用法
-
创建类,然后在创建的头文件和源文件里面添加上述代码
-
在UI界面里面拖拽widget部件
-
将widget部件提升为自定义的类,在提升的类名称里面填入上面源代码里面的类名
-
调用函数如下,在设计师界面类里面调用这个函数即可
void GaugePanel::setValue(int value)
{
setValue(double(value));
}
ui->gaugepanel->setValue(a);