Qt5--雷达图

源博客:http://www.fearlazy.com/index.php/post/31.html
工程文件下载

这位大神写的好,便于学习所以将它记录到这里。

使用Qt的Widget来实现一个雷达扫描的图像。
工程架构图:
这里写图片描述

雷达效果包括三个部分:背景、转动的扇形和闪烁的点。
1.背景的实现很简单,首先填充背景色,然后绘制横纵坐标轴以及三个同心圆。代码如下:

//背景
    painter.fillRect(rect(),QColor(15,45,188));

    //边长
    int len = m_drawArea.width();

    //底盘(x轴、y轴和3个圆)
    painter.setPen(QPen(Qt::white));
    painter.drawLine(m_drawArea.topLeft() + QPoint(0,len/2),m_drawArea.topRight() + QPoint(0,len/2));
    painter.drawLine(m_drawArea.topLeft() + QPoint(len/2,0),m_drawArea.bottomLeft() + QPoint(len/2,0));
    painter.drawEllipse(m_drawArea.center(),len/2,len/2);
    painter.drawEllipse(m_drawArea.center(),len/3,len/3);
    painter.drawEllipse(m_drawArea.center(),len/6,len/6);

在这里有个m_drawArea是用来描述绘制雷达的区域的。先确定这个绘制区域,更容易计算绘制的内容。 m_drawArea的大小在resizeEvent事件中确定。

void CRadar::resizeEvent(QResizeEvent *event)
{
    //以较短的边长作为绘制区域边长
    if(width() > height())
    {
        m_drawArea = QRect((width() - height())/2,0,height(),height());
    }
    else
    {
        m_drawArea = QRect(0,(height() - width())/2,width(),width());
    }

    m_drawArea.adjust(10,10,-10,-10);
}

为了确保雷达为圆形,我们以较短的边作为矩形的边长。然后使用adjust缩小一点。adjust前两个参数为左上角x和y的增量,后两个参数为右下角x和y的增量。

2.转动部分由一个扇形和一条直线组成。扇形使用了锥形渐变色。代码如下:

    //转动部分
        //---//线
    qreal x = m_drawArea.center().x() + (qreal)len/2 * cos(-m_pieRotate*3.14159/180);
    qreal y = m_drawArea.center().y() + (qreal)len/2 * sin(-m_pieRotate*3.14159/180);
    painter.setPen(QPen(Qt::white));
    painter.drawLine(m_drawArea.center(),QPointF(x,y));

       //----//扇形
    QConicalGradient gradient;
    gradient.setCenter(m_drawArea.center());
    gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。
    gradient.setColorAt(0.4,QColor(255,255,255,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
    gradient.setColorAt(0.8,QColor(255,255,255,0));
    painter.setBrush(QBrush(gradient));
    painter.setPen(Qt::NoPen);
    painter.drawPie(m_drawArea,m_pieRotate*16,90*16);

直线的绘制很简单,只需要计算转动角度对应圆上的点的坐标即可。扇形的绘制也很简单。难点在于渐变色的应用,由于锥形渐变是逆时针的,而我们的雷达是顺时针的转动。所以要计算好扇形区域在渐变的哪个范围。这里设置了渐变角度为扇形角度旋转180度,那么扇形区域应该在渐变角度的0.5 - 0.75范围内。由于这里使用的是int类型,怕计算的不精确,将渐变颜色的范围设置大一些。

3.第三部分是随机闪烁的点,用来点缀。在这里使用了一个list存放点的坐标,另一个list存放这些点的颜色alapha值。使用一个定时器随机改变这些点的坐标值和alapha值。


void CRadar::timerEvent(QTimerEvent *event)
{
    if(m_timerId == event->timerId())
    {
        m_pieRotate -= 10;
        update();
    }
    else if(m_pointTimerId == event->timerId())
    {
        //随机更换装饰的点
        for(int i = 0; i < m_points.count(); ++i)
        {
            int offsetX = rand()%m_drawArea.width();
            int offsetY = rand()%m_drawArea.width();
            int alapha = rand()%255;
            m_points.replace(i,QPoint(offsetX,offsetY) + m_drawArea.topLeft());
            m_pointsAlapha.replace(i,alapha);
        }

        update();
    }
}

第一个定时器是用来改变转动部分的角度的。第二个定时器才是用来改变闪烁点的。


cradar.h

#ifndef CRADAR_H
#define CRADAR_H

/*************************************************
作者:fearlazy
博客:www.fearlazy.com
描述: 仿雷达扫描效果(Qt绘制学习实践)
**************************************************/

#include <QWidget>

class CRadar : public QWidget
{
    Q_OBJECT
public:
    explicit CRadar(QWidget *parent = nullptr);
protected:
    void paintEvent(QPaintEvent *event);    //绘制事件
    void resizeEvent(QResizeEvent *event);  //大小重置事件
    void timerEvent(QTimerEvent *event);    //定时器事件
private:
    QRect         m_drawArea;      //绘制区域
    int           m_pieRotate;     //扇形旋转区域
    int           m_timerId;       //定时器ID
    int           m_pointTimerId;  //变更点定时器
    int           m_nSpeed;        //速度
    QList<QPoint> m_points;        //绘制点
    QList<int>    m_pointsAlapha;  //绘制点颜色alapha值
};

#endif // CRADAR_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H

cradar.cpp

#include "cradar.h"
#include <QPainter>
#include <QTimerEvent>
#include <QConicalGradient>
#include <qDebug>

CRadar::CRadar(QWidget *parent) : QWidget(parent)
{
    //初始化
    m_pieRotate = 0;
    m_timerId = -1;
    m_nSpeed = 50;
    m_points<<QPoint()<<QPoint()<<QPoint()<<QPoint()<<QPoint();
    m_pointsAlapha<<100<<100<<100<<100<<100;

    //启动定时器
    m_timerId = startTimer(m_nSpeed);
    m_pointTimerId = startTimer(1200);
}

void CRadar::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    //抗锯齿
    painter.setRenderHint(QPainter::Antialiasing);

    //背景
    painter.fillRect(rect(),QColor(15,45,188));

    //边长
    int len = m_drawArea.width();

    //底盘(x轴、y轴和3个圆)
    painter.setPen(QPen(Qt::white));
    painter.drawLine(m_drawArea.topLeft() + QPoint(0,len/2),m_drawArea.topRight() + QPoint(0,len/2));
    painter.drawLine(m_drawArea.topLeft() + QPoint(len/2,0),m_drawArea.bottomLeft() + QPoint(len/2,0));
    painter.drawEllipse(m_drawArea.center(),len/2,len/2);
    painter.drawEllipse(m_drawArea.center(),len/3,len/3);
    painter.drawEllipse(m_drawArea.center(),len/6,len/6);

    //转动部分
        //---//线
    qreal x = m_drawArea.center().x() + (qreal)len/2 * cos(-m_pieRotate*3.14159/180);
    qreal y = m_drawArea.center().y() + (qreal)len/2 * sin(-m_pieRotate*3.14159/180);
    painter.setPen(QPen(Qt::white));
    painter.drawLine(m_drawArea.center(),QPointF(x,y));

       //----//扇形
    QConicalGradient gradient;
    gradient.setCenter(m_drawArea.center());
    gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。
    gradient.setColorAt(0.4,QColor(255,255,255,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
    gradient.setColorAt(0.8,QColor(255,255,255,0));
    painter.setBrush(QBrush(gradient));
    painter.setPen(Qt::NoPen);
    painter.drawPie(m_drawArea,m_pieRotate*16,90*16);

    //装饰-随机点
    for(int i = 0; i < m_points.count(); ++i)
    {
        int colorAlaph = m_pointsAlapha.at(i);
        painter.setPen(QPen(QColor(255,255,255,colorAlaph),3));
        painter.drawPoint(m_points.at(i));
    }

    //更详细解释参考:http://fearlazy.com/index.php/post/31.html
}

void CRadar::resizeEvent(QResizeEvent *event)
{
    //以较短的边长作为绘制区域边长
    if(width() > height())
    {
        m_drawArea = QRect((width() - height())/2,0,height(),height());
    }
    else
    {
        m_drawArea = QRect(0,(height() - width())/2,width(),width());
    }

    m_drawArea.adjust(10,10,-10,-10);
}

void CRadar::timerEvent(QTimerEvent *event)
{
    if(m_timerId == event->timerId())
    {
        m_pieRotate -= 10;
        update();
    }
    else if(m_pointTimerId == event->timerId())
    {
        //随机更换装饰的点
        for(int i = 0; i < m_points.count(); ++i)
        {
            int offsetX = rand()%m_drawArea.width();
            int offsetY = rand()%m_drawArea.width();
            int alapha = rand()%255;
            m_points.replace(i,QPoint(offsetX,offsetY) + m_drawArea.topLeft());
            m_pointsAlapha.replace(i,alapha);
        }

        update();
    }
}


main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

widget.cpp

#include "widget.h"
#include "cradar.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    CRadar* radar = new CRadar(this);
    radar->setFixedSize(300,300);
    radar->move(50,50);
}

Widget::~Widget()
{

}

效果图:

这里写图片描述

  • 20
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Qt是一种强大的跨平台应用程序开发框架,支持多种编程语言,如C++,JavaScript,Python等。在Qt中,可以使用QtCharts模块创建自定义维度图/雷达图。 首先,我们需要在Qt项目中添加QtCharts模块,然后在代码中包含QtCharts头文件: ``` #include <QtCharts> ``` 接下来,我们可以创建一个QChart对象,并设置标题和标签: ``` QChart *chart = new QChart(); chart->setTitle("Custom Radar Chart"); chart->setAnimationOptions(QChart::AllAnimations); ``` 然后,我们可以创建QCategoryAxis对象,它用于在雷达图中显示轴度标签: ``` QCategoryAxis *axisX = new QCategoryAxis(); axisX->append("One", 1); axisX->append("Two", 2); axisX->append("Three", 3); axisX->append("Four", 4); axisX->append("Five", 5); chart->addAxis(axisX, Qt::AlignCenter); ``` 我们还可以创建QValueAxis对象,它用于在雷达图中显示数值标签: ``` QValueAxis *axisY = new QValueAxis(); axisY->setLabelFormat("%.2f"); axisY->setRange(0, 100); chart->addAxis(axisY, Qt::AlignLeft); ``` 接下来,我们可以创建一些QLineSeries对象,并将它们添加到图表中: ``` QLineSeries *series1 = new QLineSeries(); series1->setName("Series 1"); series1->append(1, 50); series1->append(2, 80); series1->append(3, 60); series1->append(4, 20); series1->append(5, 10); chart->addSeries(series1); series1->attachAxis(axisX); series1->attachAxis(axisY); QLineSeries *series2 = new QLineSeries(); series2->setName("Series 2"); series2->append(1, 20); series2->append(2, 30); series2->append(3, 50); series2->append(4, 70); series2->append(5, 90); chart->addSeries(series2); series2->attachAxis(axisX); series2->attachAxis(axisY); ``` 最后,我们可以创建一个QChartView对象,并将其设置为主窗口的中央窗口: ``` QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); setCentralWidget(chartView); ``` 这样,就可以创建一个简单的自定义维度图/雷达图。通过修改轴度标签和数值标签,以及添加或删除QLineSeries对象,可以轻松地创建更复杂的雷达图
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值