话不多说,上代码。
头文件:
#ifndef CRADAR_H
#define CRADAR_H
/*************************************************
描述: 仿雷达扫描效果
**************************************************/
#include <QWidget>
#include "QPainter"
#include <QJsonObject>
class CRadar : public QWidget
{
Q_OBJECT
public:
explicit CRadar(QWidget *parent = nullptr);
QVector<QJsonObject> mb_points; //目标点
int home_dir; //指北偏移角度
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值
QPoint CustomRotate(QPointF point,qreal from_angle,qreal rotate);
QList<QPointF> trans(int angle,float len1,float len2);
};
#endif // CRADAR_H
cpp文件:
#include "cradar.h"
#include <QPainter>
#include <QtMath>
#include <QTimerEvent>
#include <QConicalGradient>
#include <qDebug>
#include "math.h"
CRadar::CRadar(QWidget *parent) : QWidget(parent)
{
//初始化
m_pieRotate = 0;
m_timerId = -1;
m_nSpeed = 50;
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()-30;
//底盘(x轴、y轴和4个圆)
painter.setPen(QPen(Qt::green));
//圆
painter.drawEllipse(m_drawArea.center(),len*21/40,len*21/40);
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);
int fontSize = 15;
int p_crosses = 3;//十字架数量
//坐标轴
for(int i=0; i < p_crosses; i++)
{
QLineF line1,line2;
float angle = (static_cast<float>(i) * 90.0) / (static_cast<float>(p_crosses));
line1.setP1( m_drawArea.center() );
line1.setLength( len/2);
QRectF textRect(0, 0, 4 * fontSize, fontSize + 2);
for(int c = 0; c < 4; c++)
{
line1.setAngle(angle + c*90.0 + 90.0);
painter.drawLine(line1);
line2 = QLineF(line1);
line2.setLength(len/2+6.5 );
textRect.moveCenter(line2.p2());
if(i > 0){
painter.drawText( textRect, Qt::AlignCenter, QString("%1").arg((int)(360 - (c*90 ) - angle) , 3 , 10));
}else
{
if(c == 0)
{
painter.drawText( textRect, Qt::AlignCenter,QString("0"));
}
else if(c == 1)
{
painter.drawText( textRect, Qt::AlignCenter, QString("270"));
}
else if(c == 2)
{
painter.drawText( textRect, Qt::AlignCenter, QString("180"));
}
else if(c == 3)
{
painter.drawText( textRect, Qt::AlignCenter, QString("90"));
}
}
}
}
//刻度
int num=1;
float len1 = len*21/40;
float len2;
QList<QPointF> pointArr;
for(int i=0;i<360;i++){
num++;
//10的倍数刻度要略长
if(num==11){
len2 = len/2;
pointArr = trans(i,len1,len2);
num=1;
}else{
len2 = len*41/80;
pointArr = trans(i,len1,len2);
}
//画刻度
painter.drawLine(pointArr.at(0),pointArr.at(1));
}
//转动部分
//---//线
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);
QColor linecolor(20,232,147);//设置颜色
painter.setPen(QPen(Qt::green));
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(32, 255, 77,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
gradient.setColorAt(0.8,QColor(32, 255, 77,0));
painter.setBrush(QBrush(gradient));
painter.setPen(Qt::NoPen);
painter.drawPie(m_drawArea,m_pieRotate*16,90*16);
QPixmap pixmap_n(":/images/icon-red.png");
//绘制本舰指北方向
QPixmap pixmap3(":/images/jiantou.png");
painter.translate(m_drawArea.center());
painter.rotate(-home_dir);//旋转角度
QPoint point = CustomRotate(QPoint(len/2,0),0,-90);// 使图片方向不变
painter.drawPixmap(point.x()-pixmap3.width(),point.y()-pixmap3.height(),pixmap3);
painter.resetTransform();
QPixmap pixmap2(":/images/mubiao.png");
//绘制目标点
for(int i = 0; i < mb_points.size(); i++)
{
painter.save();
int x_mb= m_drawArea.center().x()+static_cast<int>(mb_points.at(i).value("x").toDouble());
int y_mb = m_drawArea.center().y()-static_cast<int>(mb_points.at(i).value("h").toDouble());
//背景图恢复正常指向
int dir_mb = (mb_points.at(i).value("dir").toDouble())-180;
int id_mb = (mb_points.at(i).value("id").toInt());
//绘制目标点名称
painter.setPen(QColor(Qt::white));
painter.drawText(x_mb-20,y_mb+20,QString::number(id_mb));
//绘制目标航向
painter.translate(QPointF(x_mb,y_mb));
painter.rotate(dir_mb);//旋转角度
painter.drawPixmap(QPoint(-8,-8),pixmap2);
painter.restore();
}
}
QPoint CRadar::CustomRotate(QPointF point,qreal from_angle,qreal rotate)
{
qreal PI=3.141592653589;
QPointF Tmp;
qreal arc = (rotate-from_angle)/180*PI;
qreal Length = qSqrt(point.x()*point.x() +point.y()*point.y());
Tmp.setX(Length*qCos(arc));
Tmp.setY(Length*qSin(arc));
return Tmp.toPoint();
}
//将角度转为两个坐标点
QList<QPointF> CRadar::trans(int angle,float len1,float len2)
{
QList<QPointF> list;
QPointF ptResult1(m_drawArea.center());
QPointF ptResult2(m_drawArea.center());
//[角度转弧度]
float rad = qDegreesToRadians(static_cast<float>(angle));
ptResult1.setX(m_drawArea.center().x() + len1 * qSin(static_cast<qreal>(rad)));
ptResult1.setY(m_drawArea.center().y() - len1 * qCos(static_cast<qreal>(rad)));
list.append(ptResult1);
ptResult2.setX(m_drawArea.center().x() + len2 * qSin(static_cast<qreal>(rad)));
ptResult2.setY(m_drawArea.center().y() - len2 * qCos(static_cast<qreal>(rad)));
list.append(ptResult2);
return list;
}
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();
}
}
组件调用:
在需要显示雷达效果图的页面引入radar组件,然后放入widget中,
CRadar radar = new CRadar(this);
//我是直接放入了一个水平布局中
ui->horizontalLayout_26->addWidget(radar);
当雷达图里的目标点需要更换时,把存储目标点的线性链表先清空再重新赋值:
//清空原有目标信息
radar->mb_points.clear();
//targetList存储的是目标坐标等信息
if(targetList.length()<=0) return;
float m_PI = 3.1415926;
//home_dir是指北偏移角度
radar->home_dir = navigate->m_home.m_navigate.m_direction;
for(int i=0;i<targetList.length();i++){
//目标行驶方向
float m_dir=targetList.at(i).direction;
//目标坐标
float hig = targetList.at(i).y;//y坐标
float mb_x =targetList.at(i).x;//x坐标
QJsonObject jsonobj;
jsonobj.insert("x",mb_x);
jsonobj.insert("h",hig);
jsonobj.insert("dir",m_dir);
jsonobj.insert("id", targetList.at(i).m_id);//目标id
radar->mb_points.append(jsonobj);
}