QT实现的一个雷达仿真自定义控件
立即下载
资源介绍:
雷达扫描图,在影视作品中见到较多,比如飞机雷达、舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置。和仪表盘类似,仪表盘有底盘背景图、同圆、刻度、刻度值、旋转的指针。在仪表盘的基础上略作修改,比如指针换成带有余辉的扫描扇面,就能完成一个雷达扫描图
#include "Radar.h"
#include
#include
#include
Radar::Radar(QWidget *parent)
: QWidget(parent)
{
timer = new QTimer();
// 目标点默认半径为5
cir_size = 5;
flag = false;
// 监听窗口大小变化的事件
installEventFilter(this);
// 默认扫描波束宽度为圆周,即360度
pBeamWidth = 360;
ScaleFactor = 1;
ScanRate = 1;
// 默认目标点颜色为蓝色
r = 0;
g = 0;
b = 255;
//强制设置背景颜色为黑色
setPalette(Qt::black); setAutoFillBackground(true);
//用槽函数控制雷达扫描效果。
connect(timer,&QTimer::timeout,this,&Radar::timerTimeOut);
Init();
SetShowTrack(true);
SetScanParams();
}
Radar::~Radar()
{
}
void Radar::Start(int nScanPeriod)
{
timer->start(nScanPeriod);
}
void Radar::Stop()
{
flag = false;
timer->stop();
}
void Radar::Init(int nMaxDetectionDistance, int nEqualParts, int nScanPeriod, int nBeamWidth, bool bShowTrack)
{
this->pRadius = nMaxDetectionDistance;
this->pNumTurns = nEqualParts;
this->pScanPeriod = nScanPeriod;
this->pBeamWidth = nBeamWidth;
this->pShowTrack = bShowTrack;
}
void Radar::SetShowTrack(bool bShowTrack)
{
this->pShowTrack = bShowTrack;
}
void Radar::SetScanPeriod(int nScanPeriod)
{
timer->stop();
this->pScanPeriod = nScanPeriod;
timer->start(nScanPeriod);
}
void Radar::SetScanParams(ScanDirectionEnum scanDirection, ScanModeEnum scanMode,
int nBeamWidth, int nStartAngle, int nEndAngle)
{
timer->stop();
this->pScanDirection = scanDirection;
this->pScanMode = scanMode;
this->pBeamWidth = nBeamWidth;
this->pStartAngle = nStartAngle;
this->pEndAngle = nEndAngle;
_start = pStartAngle;
_end = pEndAngle - pBeamWidth;
timer->start(pScanPeriod);
}
void Radar::SetData(TargetInfo ti)
{
this->pTargetInfo = ti;
}
void Radar::SetData(std::vector &ti)
{
this->pTargetInfos = ti;
}
void Radar::SetColor(int r, int g, int b)
{
this->r = r;
this->g = g;
this->b = b;
}
void Radar::timerTimeOut()
{
if(pScanMode == CircleScan)
{
if(pScanDirection == ClockWize)
{
if(!flag)
{
pStartAngle = 90;
flag = true;
}
pBeamWidth = 360;
//每次旋转ScanRate度
pStartAngle -= ScanRate;
if(pStartAngle <= -360)
{
pStartAngle = 0;
}
}
else
{
if(!flag)
{
pStartAngle = 90;
flag = true;
}
pBeamWidth = 360;
//每次旋转ScanRate度
pStartAngle += ScanRate;
if(pStartAngle >= 360)
{
pStartAngle = 0;
}
}
}
else if(pScanMode == SectorScan)
{
//每次旋转ScanRate度
pStartAngle -= ScanRate;
if(pStartAngle < _start || pStartAngle > _end)
{
ScanRate *= -1;
}
}
update();
}
void Radar::paintEvent(QPaintEvent *event)//此函数自动执行,实现扫描动画效果
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QPen(qRgba(128, 255, 0,250)));
// 圆心
CoorX = this->width() / 2;
CoorY = this->height() / 2;
// 获取窗口的宽度和高度
int width = this->width();
int height = this->height();
// 计算最小边长
minSide = qMin(width, height) - 50;
// 求量程
int range = pRadius / pNumTurns;
MeasureRadius = minSide / 2;
int range1 = MeasureRadius / pNumTurns;
// 从外到内画圆
QPoint center(CoorX,CoorY);
for(int i = 0;i < pNumTurns;i++)
{
painter.drawEllipse(center, ScaleFactor * (MeasureRadius - range1 * i),
ScaleFactor * (MeasureRadius - range1 * i));
}
// 画量程
drawRange(&painter, CoorX, CoorY, range, range1);
/** 画外圈刻度值,将坐标系移动到圆心 **/
painter.translate(CoorX, CoorY);
painter.setPen(QPen(qRgba(255, 255, 0,250)));
painter.setFont(QFont("Calibri",10));
for(int i=1;i<=360;i++){
painter.rotate(1);
painter.drawLine(0, ScaleFactor * (MeasureRadius * -1), 0, ScaleFactor * (MeasureRadius * -1 + 5));
}
for(int i=1;i<=72;i++){
painter.rotate(5);
painter.drawLine(0, ScaleFactor * (MeasureRadius * -1), 0, ScaleFactor * (MeasureRadius * -1 + 8));
}
for(int i=1;i<=36;i++){
painter.setRenderHint(QPainter::Antialiasing);
painter.rotate(10);
painter.drawLine(0, ScaleFactor * (MeasureRadius * -1),0, ScaleFactor * (MeasureRadius * -1 + 12));
}
for(int i = 1;i <= 4;i++){
// 外圈刻度值
painter.drawLine(0, 0, 0, ScaleFactor * (MeasureRadius * -1));
// 绘制方位
drawAzimuth(&painter, -10, ScaleFactor * (MeasureRadius * -1 - 10), (i - 1) * 90);
// 顺时针旋转90度
painter.rotate(90);
}
painter.translate(-CoorX,-CoorY);//恢复坐标系
painter.setPen(QPen(Qt::NoPen));//去掉外框线
// 圆周扫描
if(pScanMode == CircleScan)
{
/** 绘制扫描效果 **/
if(pScanDirection == ClockWize)
{
QConicalGradient gradient(CoorX, CoorY, pStartAngle);
gradient.setColorAt(0.1, QColor(128, 255, 0, 150));
gradient.setColorAt(0.9, QColor(0, 255, 0, 0));//尾部
painter.setBrush(gradient);
}
else if(pScanDirection == AntiClockWize)
{
QConicalGradient gradient(CoorX, CoorY, pStartAngle);
gradient.setColorAt(0.9, QColor(128, 255, 0, 150));
gradient.setColorAt(0.1, QColor(0, 255, 0, 0));//尾部
painter.setBrush(gradient);
}
painter.drawPie(CoorX-ScaleFactor * MeasureRadius, CoorY-ScaleFactor * MeasureRadius,
ScaleFactor * MeasureRadius * 2, ScaleFactor * MeasureRadius * 2,
-pStartAngle * 16, pBeamWidth * 16);
}// 扇形扫描
else if(pScanMode == SectorScan)
{
painter.setBrush(QBrush(QColor(128, 255, 0, 150)));
painter.save();
QTransform transform;
transform.translate(CoorX, CoorY); // 平移原点位置
painter.setTransform(transform); // 应用变换矩阵
painter.rotate(-90);
painter.drawPie(-ScaleFactor * MeasureRadius, -ScaleFactor * MeasureRadius,
ScaleFactor * MeasureRadius * 2, ScaleFactor * MeasureRadius * 2,
-pStartAngle * 16, -pBeamWidth * 16);
painter.restore();
}
//模拟画出可疑点
painter.translate(CoorX, CoorY);
painter.setBrush(QBrush(QColor(50, 255, 200, 200)));
if(pTargetInfo.sTargetId.size() != 0)
{
drawTarget(&painter, pTargetInfo);
}
// 绘制多点坐标数据
for(auto target : pTargetInfos)
{
drawTarget(&painter, target);
}
}
void Radar::resizeEvent(QResizeEvent *event)
{
// 窗口大小改变时重新绘制
Q_UNUSED(event);
update();
}
void Radar::wheelEvent(QWheelEvent *event)
{
int angleDelta = event->angleDelta().y();
qreal scaleFactorDelta = 1;
if (angleDelta > 0) {
// 滚轮向前滚动,放大图形
ScaleFactor += scaleFactorDelta;
} else {
// 滚轮向后滚动,缩小图形
ScaleFactor -= scaleFactorDelta;
}
// 限制放大缩小比例的范围
if (ScaleFactor < 1)
{
ScaleFactor = 1;
}
else if (ScaleFactor > 5)
{
ScaleFactor = 5;
}
// 更新小部件进行重绘
update();
}
void Radar::drawAzimuth(QPainter *painter, int x, int y, int azimuth)
{
if(azimuth == 180)
{