实现多辐射源点在内环分散显示 + 1 秒超时消失 + 对外接口封装的最小改动方案如下,仅新增必要的点管理逻辑、绘图逻辑和外部接口,不破坏原有雷达图绘制结构:
第一步:头文件(RadarWidget.h)添加核心定义与接口
运行
#include
#include
#include
#include
#include
// 1. 定义辐射源点结构体:包含时间、方位(用于内环分散)、编号等核心属性
struct RadarPoint {
int id; // 辐射源编号(区分不同点)
QDateTime captureTime; // 截获时间
double azimuth; // 方位角(0-360°,用于内环不同位置绘制)
};
class RadarWidget : public QWidget
{
Q_OBJECT
public:
explicit RadarWidget(QWidget *parent = nullptr);
// 2. 对外接口:添加辐射源点(外部调用此接口传点)
void addRadarPoint(int id, double azimuth);
// 3. 对外接口:手动清空所有点(可选)
void clearAllPoints();
protected:
void paintEvent(QPaintEvent *event) override;
private:
QList m_radarPoints; // 存储所有有效辐射源点
QTimer* m_repaintTimer; // 你的原有刷新定时器
const int TIMEOUT_MS = 1000; // 超时时间1秒
const int INNER_RING_RADIUS_RATIO = 3; // 内环半径为最大半径的3/4(和你原有彩色环内环一致)
};
第二步:源文件(RadarWidget.cpp)实现逻辑与绘图
在你原有代码基础上,补充超时清理、点添加、内环分散绘制的逻辑:
cpp
运行
#include "RadarWidget.h"
#include
:
QWidget(parent)
{
// 你的原有定时器逻辑(保留)
m_repaintTimer = new QTimer(this);
m_repaintTimer-\>setInterval(1000);
connect(m_repaintTimer, \&QTimer::timeout, this, [=]() {
update(QRect(0, 0, 200, 100));
update(QRect(width()-50, 0, 50, height()));
});
m_repaintTimer-\>start(); // 打开定时器,保证实时刷新超时点
}
// 实现对外添加点的接口
void RadarWidget::addRadarPoint(int id, double azimuth)
{
// 先检查是否已有同编号点,有则更新截获时间,无则新增
bool isUpdated = false;
for (int i = 0; i < m_radarPoints.size(); ++i) {
if (m_radarPoints[i].id == id) {
m_radarPoints[i].captureTime = QDateTime::currentDateTime();
isUpdated = true;
break;
}
}
if (!isUpdated) {
RadarPoint newPoint;
newPoint.id = id;
newPoint.captureTime = QDateTime::currentDateTime();
newPoint.azimuth = azimuth; // 外部传入的方位角(0-360°)
m_radarPoints.append(newPoint);
}
update(); // 触发重绘
}
// 实现清空所有点的接口
void RadarWidget::clearAllPoints()
{
m_radarPoints.clear();
update();
}
void RadarWidget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.fillRect(rect(), Qt::black);
// 你的原有雷达图绘制逻辑(完全保留)
int w = width();
int h = height();
int centerX = w / 2;
int centerY = h / 2 - 10;
int radius = qMin(centerX - 70, centerY - 40); // 你的最大半径
int innerR = radius * INNER_RING_RADIUS_RATIO / 4; // 内环半径(和彩色环内环一致)
// 绘制同心圆、彩色环(复制你原有代码,此处省略,保留你的原始实现即可)
// ...(你的同心圆、彩色环绘制代码)...
// ===== 新增核心逻辑 =====
// 1. 清理超时的点(从后往前遍历,避免删除元素导致索引错乱)
QDateTime currentTime = QDateTime::currentDateTime();
for (int i = m_radarPoints.size() - 1; i >= 0; --i) {
qint64 timeDiff = m_radarPoints[i].captureTime.msecsTo(currentTime);
if (timeDiff > TIMEOUT_MS) {
m_radarPoints.removeAt(i);
}
}
// 2. 在内环内分散绘制品红色点(根据方位角计算坐标)
p.setPen(QPen(Qt::magenta, 2));
p.setBrush(Qt::magenta);
int pointSize = 8; // 点的大小,可调整
for (const RadarPoint& point : m_radarPoints) {
// 将方位角转换为弧度(Qt中角度顺时针,数学中逆时针,需调整)
double rad = (90 - point.azimuth) * M_PI / 180.0;
// 计算点在内环内的坐标(距离中心的距离为内环半径的随机比例,避免完全重叠)
double randomRatio = 0.3 + (qrand() % 8) * 0.1; // 0.3~1.0的随机比例,保证在内环内
int x = centerX + innerR * randomRatio * cos(rad);
int y = centerY - innerR * randomRatio * sin(rad);
// 绘制点
p.drawEllipse(x - pointSize/2, y - pointSize/2, pointSize, pointSize);
}
}
第三步:外部调用接口示例(如MainWindow中)
外部只需调用addRadarPoint即可传入点,无需关心内部超时和绘制逻辑:
cpp
运行
#include "RadarWidget.h"
#include
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
RadarWidget *radar = new RadarWidget(this);
setCentralWidget(radar);
// 示例1:添加编号1、方位角45°的辐射源点
radar->addRadarPoint(1, 45.0);
// 示例2:添加编号2、方位角180°的辐射源点
radar->addRadarPoint(2, 180.0);
// 示例3:500ms后更新编号1的点(重置超时时间)
QTimer::singleShot(500, [=]() {
radar->addRadarPoint(1, 45.0);
});
}
核心逻辑说明
超时清理:在paintEvent中遍历点列表,计算当前时间与截获时间的差值,超过 1 秒则移除,定时器每秒刷新保证实时性;
内环分散显示:根据每个点的方位角计算极坐标,再转换为屏幕坐标,同时加入随机比例,让点在内环内分散不重叠;
对外接口:仅暴露addRadarPoint(添加 / 更新点)和clearAllPoints(清空点),内部逻辑完全封装,外部调用极简。