小伙伴们大家好,之前我上传了一个资源(骗积分用的),但是没有效果图和博文与之对应,所以大家应该是都不敢下载的吧,
先上资源链接 : 一个雷达图和一个摇杆图(方向可以根据你自己的需要增加)资源
再上效果图。
这个是项目对应的图片
接下来为了保证文章质量,介绍一下两个控件吧,首先说明这知识一个widget,并没有封装到Qt Designer内,如果你有兴趣可以自己加上封装。
介绍一下代码吧,按照图上的顺序,先介绍这个摇杆图:
主要代码:
void RockingBar::drawRing(QPainter &painter)
{
int r = radius_ - 20;
painter.save();
QColor color_1("#47D72D"); color_1.setAlpha(60);
QPen pen(color_1);
pen.setCapStyle(Qt::RoundCap);
QRectF rect = QRectF(-r, -r, 2*r, 2*r);
QPainterPath path;
path.moveTo(cos(16 *M_PI / 180 ) * r, -sin(16 *M_PI / 180)*r);
path.arcTo(rect, 15, -30);
path.moveTo(cos(106 *M_PI / 180 ) * r, -sin(106 *M_PI / 180)*r);
path.arcTo(rect, 105, -30);
path.moveTo(cos(196 *M_PI / 180 ) * r, -sin(196 *M_PI / 180)*r);
path.arcTo(rect, 195, -30);
path.moveTo(cos(286 *M_PI / 180 ) * r, -sin(286 *M_PI / 180)*r);
path.arcTo(rect, 285, -30);
pen.setWidth(10);
painter.setPen(pen);
painter.drawPath(path);
QRectF rect2 = QRectF(-r + 10, -r + 10, 2*r - 20, 2*r- 20);
pen.setWidth(4);
color_1.setAlpha(100);
pen.setColor(color_1);
painter.setPen(pen);
painter.drawEllipse(rect2);
painter.restore();
}
void RockingBar::drawDirection(QPainter &painter)
{
painter.save();
QColor color_1("#47D72D"); color_1.setAlpha(200);
QPen pen(color_1);
QPainterPath path;
QVector<QPointF> points{
{ -5.0, -40.0},
{ 5.0, -40.0},
{ 0.0, -40 + 10 * cos(60)},
};
QVector<QPointF> points2{
{ -5.0, 40.0},
{ 5.0, 40.0},
{ 0.0, 40 - 10 * cos(60)},
};
QVector<QPointF> points3{
{ -40, 5.0},
{ -40, -5.0},
{ -40 - 10 * cos(120), 0.0},
};
QVector<QPointF> points4{
{ 40, 5.0},
{ 40, -5.0},
{ 40 + 10 * cos(120), 0.0},
};
QPolygonF triangle;
triangle.append(points);//三点坐标
QPolygonF triangle2;
triangle2.append(points2);//三点坐标
QPolygonF triangle3;
triangle3.append(points3);//三点坐标
QPolygonF triangle4;
triangle4.append(points4);//三点坐标
path.addPolygon(triangle);
path.addPolygon(triangle2);
path.addPolygon(triangle3);
path.addPolygon(triangle4);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::green);
painter.drawPath(path); //画三角形
painter.restore();
}
void RockingBar::drawRocker(QPainter &painter)
{
int r = 15;
painter.save();
painter.translate(rocker_center_);
QColor color_1("#47D72D"); color_1.setAlpha(200);
QPen pen(color_1);
QRectF rect2 = QRectF(-r, -r, 2*r, 2*r);
pen.setColor(color_1);
painter.setPen(Qt::NoPen);
painter.setBrush(color_1);
painter.drawEllipse(rect2);
pen.setWidth(1);
color_1.setAlpha(120);
pen.setColor(color_1);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
rect2 = QRectF(-r -2, -r -2, 2*r+4, 2*r+4);
painter.drawEllipse(rect2);
painter.restore();
}
void RockingBar::mousePressEvent(QMouseEvent *event)
{
mouse_pressed_ = true;
}
void RockingBar::mouseMoveEvent(QMouseEvent *event)
{
if(!mouse_pressed_)
{
return;
}
int width = this->width() / 2;
int height = this->height() /2;
QPointF point;
point.setX((event->pos().x() - width) / scale_);
point.setY((event->pos().y() - height) / scale_);
int distance = point.x() * point.x() + point.y() * point.y();
if(distance > 47 * 47)
{
double scale = 47.0 / sqrt(distance) ;
point *= scale;
}
rocker_center_ = point;
update();
}
void RockingBar::mouseReleaseEvent(QMouseEvent *event)
{
mouse_pressed_ = false;
rocker_center_ = QPointF(0.0, 0.0);
update();
}
我觉得我的函数名称挺明确的,怎么介绍呢,就不介绍了,直接看 函数名称应该是能理解的,drawDirection 现在是写死的,如果是自己使用的话,最好是根据圆的规则写成一个数量的成员变量。
再介绍这个雷达图,
主要代码:
#include "radargpu.h"
#include
#include
#include
RadarGpu::RadarGpu(QWidget *parent)
: QOpenGLWidget(parent)
{
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setSamples(6);
setFormat(format);
connect(&timer_, SIGNAL(timeout()), this, SLOT(timeout()));
timer_.start(20);
}
RadarGpu::~RadarGpu()
{
}
void RadarGpu::mousePressEvent(QMouseEvent *event)
{
int width = this->width() / 2;
int height = this->height() /2;
QPoint point;
point.setX((event->pos().x() - width) / scale_);
point.setY((event->pos().y() - height) / scale_);
if(point.x() * point.x() + point.y() * point.y() > (83 * 83))
{
return;
}
points_.append(point);
}
void RadarGpu::timeout()
{
rotate_radius_+=6;
if(rotate_radius_ == 360)
{
rotate_radius_ = 0;
}
update();
}
void RadarGpu::paintGL()
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing, true);
painter.setRenderHints(QPainter::TextAntialiasing, true);
painter.translate(width / 2, height / 2);
scale_ = side / 200.0;
painter.scale(scale_, scale_);
drawScale(painter);
drawRing(painter);
drawScaleNum(painter);
drawScanArea(painter);
drawTarget(painter);
}
void RadarGpu::drawScale(QPainter &painter)
{
int radius = radius_-12;
painter.save();
QPen pen;
pen.setCapStyle(Qt::RoundCap);
painter.rotate(start_angle_);
int steps = (long_scale_ * short_scale_);
double angleStep = (360.0 - start_angle_ - end_angle_) / steps;
//计算圆环对应大刻度范围索引
int indexStart = steps * (double)ring_start_ / 100 + 1;
int indexMid = steps * (double)ring_middle_ / 100 - 1;
int indexEnd = steps * (double)ring_end_ / 100 + 1;
int index = 0;
for (int i = 0; i <= steps; i++)
{
if (i % short_scale_ == 0)
{
//根据所在圆环范围切换颜色
if (index < indexStart)
{
pen.setColor(ring_start_color_);
} else if (index < (indexStart + indexMid))
{
pen.setColor(ring_middle_color_);
} else if (index < (indexStart + indexMid + indexEnd))
{
pen.setColor(ring_end_color_);
}
index++;
pen.setWidthF(0.5);
painter.setPen(pen);
painter.drawLine(0, radius - 12, 0, radius);
} else {
pen.setWidthF(0.5);
pen.setColor(QColor(0,255,255));
painter.setPen(pen);
painter.drawLine(0, radius - 5, 0, radius);
}
painter.rotate(angleStep);
}
painter.restore();
}
void RadarGpu::drawScaleNum(QPainter &painter)
{
int radius = radius_- 6;
painter.save();
painter.setPen(text_color_);
QFont font;
font.setPixelSize(6);
painter.setFont(font);
double startRad = (360 - start_angle_ - 90) * (M_PI / 180);
double deltaRad = (360 - start_angle_ - end_angle_) * (M_PI / 180) / long_scale_;
for (int i = 0; i < long_scale_; i++)
{
double sina = qSin(startRad - i * deltaRad);
double cosa = qCos(startRad - i * deltaRad);
double value = 1.0 * i * ((max_value_ - min_value_) / long_scale_) + min_value_;
QString strValue = QString("%1").arg((double)value, 0, 'f', precision_);
double textWidth = painter.fontMetrics().width(strValue);
double textHeight = painter.fontMetrics().height();
double x = radius * cosa - textWidth / 2.0;
double y = -radius * sina + textHeight / 2.0;
painter.drawText(QPointF(x, y), strValue);
}
painter.restore();
}
void RadarGpu::drawRing(QPainter &painter)
{
int r = radius_;
painter.save();
double scale = 1.0 / ring_nums_;
for(int i = 0; i < ring_nums_; ++i)
{
r = radius_ * (scale * i);
painter.setPen(QPen(Qt::green, 1));
painter.drawEllipse(-r, -r, r * 2, r * 2);
}
painter.setPen(QPen(Qt::green, 1));
painter.drawLine(0, -r, 0, r);
painter.drawLine(-r, 0, r, 0);
painter.restore();
}
void RadarGpu::drawScanArea(QPainter &painter)
{
// 画扫描区域
int r = radius_ -11;
painter.save();
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.rotate(rotate_radius_);
QColor color_0("#47D72D"); color_0.setAlpha(200);
QColor color_2("#47D72D"); color_2.setAlpha(0);
//绘制扫描线
painter.setPen(QPen(color_0, 0));
painter.drawLine(QPoint(0, 0), QPoint(radius_ - 12, 0));
//绘制扫描线拖尾
QConicalGradient scanAreaGradient(QPoint(0, 0), 0);
scanAreaGradient.setColorAt(0.0, color_0);
scanAreaGradient.setColorAt(1. / 360, color_0);
scanAreaGradient.setColorAt(120. / 360, color_2);
painter.setPen(Qt::NoPen);
painter.setBrush(scanAreaGradient);
painter.drawPie(QRect(-r, -r, r*2, r*2), 0, 120 * 16);
painter.restore();
}
void RadarGpu::drawTarget(QPainter &painter)
{
painter.save();
QColor color_0("#ffffff"); color_0.setAlpha(250);
QColor color_4("#ffffff"); color_4.setAlpha(200);
QColor color_1("#47D72D"); color_1.setAlpha(200);
QColor color_2("#47D72D"); color_2.setAlpha(0);
for (int i = 0; i < points_.count(); ++i)
{
painter.setPen(Qt::NoPen);
QRadialGradient radialGradient(points_.at(i), 3, points_.at(i));
radialGradient.setColorAt(0.0,color_0);
radialGradient.setColorAt(0.1,color_4);
radialGradient.setColorAt(0.2,color_1);
radialGradient.setColorAt(1.0,color_2);
painter.setBrush(radialGradient);
painter.drawEllipse(points_.at(i).x()-3,points_.at(i).y()-3,6,6);
}
painter.restore();
}
我觉得我的函数名称已经可以代替介绍了,我传的代码都是加了注释的,不用担心看不懂哦,当然你要是完全没有基础则当我没说。
雷达图比摇杆图稍微复杂一点,资源里面提供了两个版本的,资源里面还有一个汽车的仪表盘,没有显示出来.其实这种的绘制只要是一个能做出来之后后续的只要有样式应该是都不复杂,都可以实现的。
不需要每一个都看别人怎么写,应该是自己能理解的。要窥一斑而知全豹。