QT实现雷达图和摇杆图

简介: 小伙伴们大家好,之前我上传了一个资源(骗积分用的),但是没有效果图和博文与之对应,所以大家应该是都不敢下载的吧,先上资源链接 : 一个雷达图和一个摇杆图(方向可以根据你自己的需要增加)资源再上效果图。

QT雷达图和摇杆图

小伙伴们大家好,之前我上传了一个资源(骗积分用的),但是没有效果图和博文与之对应,所以大家应该是都不敢下载的吧,


先上资源链接 : 一个雷达图和一个摇杆图(方向可以根据你自己的需要增加)资源


再上效果图。


摇杆图

0f16e9b0947e4184a38c7b89c92601e0.gif

雷达图

image.gif


这个是项目对应的图片


接下来为了保证文章质量,介绍一下两个控件吧,首先说明这知识一个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 <QPainter>
#include <QtMath>
#include <QMouseEvent>
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();
}

我觉得我的函数名称已经可以代替介绍了,我传的代码都是加了注释的,不用担心看不懂哦,当然你要是完全没有基础则当我没说。


注:

雷达图比摇杆图稍微复杂一点,资源里面提供了两个版本的,资源里面还有一个汽车的仪表盘,没有显示出来.其实这种的绘制只要是一个能做出来之后后续的只要有样式应该是都不复杂,都可以实现的。


不需要每一个都看别人怎么写,应该是自己能理解的。要窥一斑而知全豹。

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
存储 安全 算法
Qt QSet 详解:从底层原理到高级用法
Qt QSet 详解:从底层原理到高级用法
1646 0
|
传感器 存储 监控
自动施肥系统
自动施肥系统
316 2
|
7月前
|
数据处理 索引
基于Qt和OpenGL的雷达显示实例
基于Qt和OpenGL的雷达显示实例
312 0
undefined reference to symbol 'dlsym@@GLIBC_2.17' libdl.so: error adding symbols: DSO missing from c
undefined reference to symbol 'dlsym@@GLIBC_2.17' libdl.so: error adding symbols: DSO missing from c
1008 0
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明
1134 0
|
API UED
【Qt 学习笔记】Qt窗口 | 状态栏 | QStatusBar的使用及说明
【Qt 学习笔记】Qt窗口 | 状态栏 | QStatusBar的使用及说明
2753 4
|
编译器 C语言
Qt使用MSVC编译错误: LNK2019: 无法解析的外部符号
Qt使用MSVC编译错误: LNK2019: 无法解析的外部符号
1314 1
成功解决:Failed to load resource: net::ERR_FILE_NOT_FOUND
这篇文章提供了解决"Failed to load resource: net::ERR_FILE_NOT_FOUND"错误的步骤,通过修改配置文件中的资源路径设置为相对路径"./"来成功运行打包后的项目。
成功解决:Failed to load resource: net::ERR_FILE_NOT_FOUND
QComboBox设置下拉item大小
QComboBox设置下拉item大小
776 0
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
474 0

热门文章

最新文章