Qt AFSim雷达显控端-战术显示面板
概述
战术显示面板组件,用于在战术系统中可视化显示高度-距离图和甘特图。该组件不依赖外部 NCS 代码,仅使用 Qt 框架实现,提供了完整的战术信息展示和交互功能。

主要特性
- 高度-距离图:显示武器覆盖范围的多边形区域(单位:千米)
- 甘特图:显示战术条目的时间/距离序列
- 标尺:显示距离刻度,支持当前位置指示
- 选中点追踪:支持目标点选择和历史轨迹记录
- 武器选择:支持多武器切换和范围自动调整
- 交互支持:支持鼠标点击、区域进入/退出事件
界面布局
┌─────────────────────────────────────────┐
│ 标题区域 (距离基准、武器选择) │
├─────────────────────────────────────────┤
│ │
│ 高度-距离图 (Chart) │
│ (显示多边形覆盖范围) │
│ │
├─────────────────────────────────────────┤
│ 标尺 (Ruler) - 距离刻度 │
├─────────────────────────────────────────┤
│ │
│ 甘特图 (Gantt) │
│ (显示战术条目) │
│ │
└─────────────────────────────────────────┘
基本使用
创建实例
cpp
#include "tacticaldisplayview.h"
// 创建战术显示视图
TacticalDisplayView *tacticalView = new TacticalDisplayView(parent);
tacticalView->setMinimumWidth(360);
tacticalView->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
设置基本参数
cpp
// 设置距离范围(单位:千米)
tacticalView->setRange(0.0, 150.0);
// 设置高度范围(单位:千米)
tacticalView->setAltitudeRange(0.0, 30.0);
// 设置标题信息
tacticalView->setTitle("Tactical Display");
tacticalView->setRangeFrom("OwnShip");
// 设置当前标尺位置(竖线指示)
tacticalView->setCurrentPosition(55.0);
API 详解
范围设置
setRange(double minKm, double maxKm)
设置距离显示范围(X轴)。
参数:
minKm: 最小距离(千米)maxKm: 最大距离(千米)
示例:
cpp
tacticalView->setRange(0.0, 150.0); // 显示 0-150 公里范围
setAltitudeRange(double minKm, double maxKm)
设置高度显示范围(Y轴)。
参数:
minKm: 最小高度(千米)maxKm: 最大高度(千米)
默认值: 0.0 - 30.0 公里(可覆盖防空导弹等武器)
示例:
cpp
tacticalView->setAltitudeRange(0.0, 30.0);
setCurrentPosition(double km)
设置标尺当前位置,用于在标尺区域显示竖线指示。
参数:
km: 当前位置距离(千米)
示例:
cpp
tacticalView->setCurrentPosition(55.0);
currentPosition() const
获取当前标尺位置。
返回值: 当前距离(千米)
setVerticalLine(double km)
设置甘特图区域内的参考竖线位置。
参数:
km: 竖线位置(千米)
setVerticalLineVisible(bool visible)
控制参考竖线的显示/隐藏。
参数:
visible: true 显示,false 隐藏
标题信息设置
setTitle(const QString &title)
设置面板标题。
setRangeFrom(const QString &rangeFrom)
设置距离基准说明(如 "OwnShip")。
setWeapon(const QString &weapon)
设置当前武器名称(不触发下拉框更新)。
setWeaponList(const QStringList &weapons)
设置武器列表,更新下拉选择框。
示例:
cpp
QStringList weapons = {"SAM-1", "SAM-2", "Cannon"};
tacticalView->setWeaponList(weapons);
setSelectedWeapon(const QString &weapon)
设置并选中指定武器,会触发范围自动调整。
示例:
cpp
tacticalView->setSelectedWeapon("SAM-1");
多边形操作
多边形用于在高度-距离图中显示武器覆盖范围。
addPolygon(const QVector<QPointF> &pointsKm, const QColor &fill, const QColor &border, const QString &label, bool hatched)
添加一个多边形到图表中。
参数:
pointsKm: 多边形顶点坐标(单位:千米),QPointF的 x 为距离,y 为高度fill: 填充颜色(默认:QColor(70, 120, 200))border: 边框颜色(默认:QColor(200, 220, 255))label: 标签文本(用于与武器名称匹配)hatched: 是否使用斜线填充(默认:false)
返回值: 多边形ID(用于后续识别)
示例:
cpp
QVector<QPointF> points;
points << QPointF(0.0, 0.0) // 起点:0km距离,0km高度
<< QPointF(50.0, 10.0) // 50km距离,10km高度
<< QPointF(100.0, 5.0) // 100km距离,5km高度
<< QPointF(50.0, 0.0); // 回到起点附近
int polyId = tacticalView->addPolygon(
points,
QColor(70, 120, 200), // 蓝色填充
QColor(200, 220, 255), // 浅蓝边框
"SAM-1", // 标签
false // 不使用斜线
);
clearPolygons()
清除所有多边形。
示例:
cpp
tacticalView->clearPolygons();
甘特图操作
甘特图用于显示战术条目的时间/距离序列。
addGanttItem(const QString &name, double startKm, double lengthKm, int row)
添加一个甘特图条目。
参数:
name: 条目名称startKm: 起始距离(千米)lengthKm: 长度(千米)row: 行号(从0开始,相同行号会重叠显示)
返回值: 甘特图条目ID
示例:
cpp
// 添加多个战术阶段
int id1 = tacticalView->addGanttItem("Detection", 0.0, 20.0, 0);
int id2 = tacticalView->addGanttItem("Tracking", 20.0, 30.0, 0);
int id3 = tacticalView->addGanttItem("Engagement", 50.0, 40.0, 1);
clearGantt()
清除所有甘特图条目。
选中点与历史轨迹
setSelectedPoint(double rangeKm, double altitudeKm, qint64 trackId)
设置当前选中的目标点。
参数:
rangeKm: 目标距离(千米)altitudeKm: 目标高度(千米)trackId: 航迹ID(用于切换目标时清除历史)
功能说明:
- 在高度-距离图中显示选中点(白色十字标记)
- 自动记录历史轨迹(每0.1秒记录一次,最多保留50个点)
- 检测目标是否进入/离开甘特图区域,触发相应信号
- 切换目标时自动清除上一个目标的历史记录
示例:
cpp
tacticalView->setSelectedPoint(55.0, 5.5, 12345);
setHistoryPoints(const QVector<QPointF> &pointsKm)
设置历史轨迹点(已废弃,历史记录由定时器自动管理)。
clearSelectedPoint()
清除选中点和历史轨迹,停止历史记录定时器。
示例:
cpp
tacticalView->clearSelectedPoint();
信号与槽
信号
polygonClicked(int id)
当用户点击多边形时发出。
参数:
id: 被点击的多边形ID
示例:
cpp
connect(tacticalView, &TacticalDisplayView::polygonClicked,
this, [](int id) {
qDebug() << "Polygon clicked:" << id;
});
ganttItemClicked(int id)
当用户点击甘特图条目时发出。
参数:
id: 被点击的甘特图条目ID
ganttRegionEntered(const QString &name)
当选中目标进入某个甘特图区域时发出。
参数:
name: 甘特图条目名称
示例:
cpp
connect(tacticalView, &TacticalDisplayView::ganttRegionEntered,
this, [](const QString &name) {
qInfo() << "[Tactical] Enemy entered Gantt region:" << name;
});
ganttRegionExited(const QString &name)
当选中目标离开某个甘特图区域时发出。
参数:
name: 甘特图条目名称
示例:
cpp
connect(tacticalView, &TacticalDisplayView::ganttRegionExited,
this, [](const QString &name) {
qInfo() << "[Tactical] Enemy exited Gantt region:" << name;
});
完整使用示例
cpp
#include "tacticaldisplayview.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建战术显示视图
TacticalDisplayView *tacticalView = new TacticalDisplayView(&window);
tacticalView->setMinimumWidth(360);
// 设置基本参数
tacticalView->setTitle("Tactical Display");
tacticalView->setRangeFrom("OwnShip");
tacticalView->setRange(0.0, 150.0);
tacticalView->setAltitudeRange(0.0, 30.0);
// 设置武器列表
QStringList weapons = {"SAM-1", "SAM-2", "Cannon"};
tacticalView->setWeaponList(weapons);
tacticalView->setSelectedWeapon("SAM-1");
// 添加武器覆盖范围多边形
QVector<QPointF> sam1Points;
sam1Points << QPointF(0.0, 0.0)
<< QPointF(80.0, 15.0)
<< QPointF(120.0, 10.0)
<< QPointF(100.0, 0.0);
tacticalView->addPolygon(sam1Points,
QColor(70, 120, 200),
QColor(200, 220, 255),
"SAM-1");
// 添加甘特图条目
tacticalView->addGanttItem("Detection Phase", 0.0, 30.0, 0);
tacticalView->addGanttItem("Tracking Phase", 30.0, 40.0, 0);
tacticalView->addGanttItem("Engagement Phase", 70.0, 50.0, 1);
// 连接信号
connect(tacticalView, &TacticalDisplayView::ganttRegionEntered,
[](const QString &name) {
qDebug() << "Entered:" << name;
});
connect(tacticalView, &TacticalDisplayView::ganttRegionExited,
[](const QString &name) {
qDebug() << "Exited:" << name;
});
// 设置选中点(模拟目标)
tacticalView->setSelectedPoint(55.0, 5.5, 12345);
layout->addWidget(tacticalView);
window.resize(800, 600);
window.show();
return app.exec();
}
坐标系统
世界坐标(World Coordinates)
- X轴(距离) :单位千米(km),范围由
setRange()设置 - Y轴(高度) :单位千米(km),范围由
setAltitudeRange()设置 - 原点:左下角为 (minRange, minAlt)
屏幕坐标(Screen Coordinates)
- 组件内部自动将世界坐标转换为屏幕坐标进行绘制
- 转换函数:
worldToScreen(const QPointF &p)
坐标转换示例
cpp
// 世界坐标:距离 50km,高度 10km
QPointF worldPoint(50.0, 10.0);
// 内部自动转换为屏幕坐标进行绘制
// 转换公式:
// screenX = chartRect.left() + (worldX - minRange) / (maxRange - minRange) * chartRect.width()
// screenY = chartRect.bottom() - (worldY - minAlt) / (maxAlt - minAlt) * chartRect.height()
颜色主题
组件使用内置的颜色主题,独立于外部 NCS 主题:
cpp
const QColor kBg = QColor(36, 79, 83); // 背景色
const QColor kPanel = QColor(20, 56, 60); // 面板色
const QColor kPanelAlt = QColor(42, 85, 90); // 面板高亮色
const QColor kFg = QColor(230, 230, 230); // 前景色(文字)
const QColor kAccent = QColor(255, 153, 0); // 强调色(选中、指示线)
const QColor kBorderDark = QColor(60, 90, 92); // 深色边框
历史轨迹功能
工作原理
- 当调用
setSelectedPoint()设置选中点时,自动启动历史记录定时器 - 定时器每 0.1 秒(100毫秒)记录一次当前选中点位置
- 最多保留 50 个历史点,超出后自动删除最旧的点
- 历史轨迹以半透明白色线条和圆点显示在高度-距离图中
- 切换目标(trackId 不同)时自动清除历史记录
使用建议
- 历史轨迹主要用于观察目标的运动趋势
- 如果目标移动过快,可以调整定时器间隔(需要修改源码)
- 历史点数量限制为 50 个,约 5 秒的历史记录
武器范围自动调整
当调用 setSelectedWeapon() 或在下拉框中选择武器时,组件会自动:
- 查找与武器名称匹配的多边形(通过
label匹配) - 计算该多边形覆盖的最大距离
- 自动调整 X 轴显示范围,使武器覆盖范围完整显示
- 范围会在最大距离基础上增加 50% 的余量,确保内容按比例缩小显示
示例:
cpp
// 添加 SAM-1 武器覆盖范围(最大距离 100km)
QVector<QPointF> points;
// ... 设置点 ...
tacticalView->addPolygon(points, ..., "SAM-1", ...);
// 选择武器后,X轴范围会自动调整为 0-150km(100 * 1.5)
tacticalView->setSelectedWeapon("SAM-1");
Group
1062801117