:详细讲解

在本篇文章中,我们将详细探讨如何使用Qt创建一个雷达轨迹系统。该系统可以模拟雷达轨迹的显示、处理用户的交互并管理轨迹选中状态。通过这篇文章,您将了解到自定义类 RadarTrackItemRadarTrackManagerOverlayWidgetRadarGridItem 的实现细节以及它们之间的协作方式。

在这里插入图片描述

1. 核心概念与组件概述

在这个雷达系统中,我们通过多个自定义类来实现不同的功能,这些类主要有:

  • RadarTrackItem:表示单个雷达轨迹,包含轨迹点、标签和选中状态的处理。
  • RadarTrackManager:管理所有的雷达轨迹,负责控制轨迹的选中状态,确保一次只有一个轨迹被选中。
  • RadarGridItem:绘制雷达的网格和扫描效果,作为背景显示在场景中。
  • OverlayWidget:叠加信息显示小部件,用于在界面上展示雷达的当前状态、系统时间等。

这些类的组合构成了一个完整的雷达轨迹系统。接下来,我们将逐一解释每个类的实现及其关键功能。


2. RadarTrackItem:雷达轨迹的实现

RadarTrackItem 是核心类之一,它用于表示和绘制单个雷达轨迹。每个 RadarTrackItem 包含以下功能:

  • 轨迹点的绘制:每个雷达轨迹由一系列坐标点组成,这些点会以小圆点的形式显示在界面上。
  • 标签显示:轨迹上会显示一个标签,表示该轨迹的名称。标签会自动跟随最新的轨迹点。
  • 选中状态的处理:轨迹可以被选中或取消选中,并且在选中时轨迹的颜色会发生变化。

代码实现如下:

// RadarTrackItem 构造函数
RadarTrackItem::RadarTrackItem(const QString &label, const QList<QPointF> &points, QGraphicsItem *parent)
    : QObject(), QGraphicsItem(parent), trackPoints(points), labelName(label), trackColor(Qt::yellow), labelColor(Qt::white), selectedState(false)
{
    // 创建航迹标签,使用自定义的 CustomTextItem
    trackLabel = new CustomTextItem(label, this);  
    trackLabel->setLabelFontSize(4);  
    trackLabel->setLabelColor(labelColor);  
    trackLabel->setPos(points.last().x(), points.last().y());

    // 设置该图元为可选中状态
    setFlag(QGraphicsItem::ItemIsSelectable);  

    // 初始化时取消选中状态
    setSelectedState(false);

    // 注册到轨迹管理器
    RadarTrackManager::instance()->registerTrack(this);

    // 设置图元的缓存模式,以提高性能
    this->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
}

// 处理标签的选中状态
void RadarTrackItem::handleSelectionChanged(bool selected)
{
    if (selected) {
        // 通知管理器取消其他航迹的选中状态
        RadarTrackManager::instance()->trackSelected(this);
    }
    setSelectedState(selected);  
}

// 绘制轨迹点和标签
void RadarTrackItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    qreal pointSize = 0.1;  
    painter->setPen(Qt::NoPen);  
    painter->setBrush(QBrush(trackColor));

    // 绘制轨迹点
    for (const QPointF &point : trackPoints) {
        painter->drawEllipse(point, pointSize, pointSize);
    }

    // 更新标签位置
    if (!trackPoints.isEmpty()) {
        trackLabel->setPos(trackPoints.last().x() + 1, trackPoints.last().y() - 1);
    }
}

该类的关键部分在于它如何处理轨迹点的绘制和轨迹标签的同步更新。通过 setSelectedState 函数,我们可以改变轨迹的选中状态,并通知管理器更新其他轨迹的状态。


3. RadarTrackManager:轨迹管理器

RadarTrackManager 负责管理所有的轨迹,并确保同时只有一个轨迹处于选中状态。它是一个单例类,保证全局只有一个实例用于管理所有轨迹。

关键功能如下:

  • 轨迹的注册:每个 RadarTrackItem 创建时都会注册到管理器中,以便统一管理。
  • 轨迹选中状态的管理:当某个轨迹被选中时,其他所有轨迹都会被取消选中,保证系统中只有一个轨迹是被选中的。

代码如下:

// 单例模式实现
RadarTrackManager* RadarTrackManager::instance()
{
    static RadarTrackManager manager;  
    return &manager;  
}

// 注册航迹
void RadarTrackManager::registerTrack(RadarTrackItem* track)
{
    tracks.append(track);
}

// 处理航迹的选中状态
void RadarTrackManager::trackSelected(RadarTrackItem* selectedTrack)
{
    QList<RadarTrackItem*> tracksToDeselect;

    // 遍历所有已注册的航迹,如果不是当前选中的航迹且已选中,则取消选中
    for (RadarTrackItem* track : tracks) {
        if (track != selectedTrack && track->isSelected()) {
            tracksToDeselect.append(track); 
        }
    }

    // 取消其他航迹的选中状态
    for (RadarTrackItem* track : tracksToDeselect) {
        track->setSelectedState(false);
    }
}

通过该管理器,系统确保了轨迹的选中逻辑简单明了,避免了多轨迹同时选中的混乱。


4. RadarGridItem:绘制雷达网格与扫描效果

RadarGridItem 类用于绘制雷达背景的网格及模拟雷达的扫描效果。该类会定时更新扫描角度,并使用渐变色来模拟雷达扫描线的移动。

主要功能如下:

  • 同心圆和径向线的绘制:雷达背景由多个同心圆和径向线组成,形成雷达网格。
  • 雷达扫描效果:通过使用 QConicalGradient 来创建雷达扫描的视觉效果,模拟雷达扫描线的旋转。

代码实现:

void RadarGridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    qreal scale = painter->worldTransform().m11();  
    qreal adjustedScale = qMax(scale, 0.1);  
    qreal penWidth = qMax(1.0 / adjustedScale, 0.5);  

    QPen gridPen(Qt::green);
    gridPen.setWidthF(penWidth);
    painter->setPen(gridPen);

    // 绘制同心圆
    for (int i = 50; i <= 200; i += 50) {
        painter->drawEllipse(QPointF(0, 0), i, i);
    }

    // 绘制径向线
    for (int angle = 0; angle < 360; angle += 30) {
        QLineF line(QPointF(0, 0), QPointF(200 * qCos(qDegreesToRadians(angle)),
                                           200 * qSin(qDegreesToRadians(angle))));
        painter->drawLine(line);
    }

    // 绘制雷达扫描的渐变区域
    QConicalGradient gradient(center, -angle * 180.0 / PI);
    gradient.setColorAt(0.0, QColor(0, 255, 0, 180));  
    gradient.setColorAt(1.0, Qt::transparent);  
    painter->setBrush(gradient);

    // 绘制扫描区域
    painter->drawPie(center.x() - radius, center.y() - radius, radius * 2, radius * 2,
                    int(-angle * 180.0 / PI * 16), 30 * 16);  
}

该类的绘制逻辑主要依赖于Qt的绘图系统,通过精确控制角度与渐变,可以生成动态的雷达扫描效果。


5. OverlayWidget:显示雷达信息

OverlayWidget 类用于显示雷达系统中的各种实时信息,例如雷达的经纬度、当前系统时间、工作时长等。这些信息会被叠加到场景中,但不会干扰用户的操作。

代码实现:

void OverlayWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制左上角的雷达信息
    painter.setPen(Qt::green);
    painter.drawText(10, 20, tc("雷达经度: 109°09'59.71\""));
    painter.drawText(10, 40, tc("雷达纬度: 34°04'55.28\""));
   

 painter.drawText(10, 60, tc("雷达高度: 588 米"));

    // 绘制右下角的系统时间信息
    painter.setPen(Qt::red);
    painter.drawText(width() - 160, height() - 60, tc("系统日期: %1").arg(QDate::currentDate().toString("yyyy-MM-dd")));
    painter.drawText(width() - 160, height() - 40, tc("系统时间: %1").arg(QDateTime::currentDateTime().toString("hh:mm:ss")));
}

6. 总结:将所有组件整合

通过这些自定义类的协作,系统可以:

  • 绘制雷达背景和网格;
  • 显示雷达扫描的动态效果;
  • 管理和显示多个雷达轨迹;
  • 处理用户与轨迹的交互,并通过 RadarTrackManager 统一管理轨迹的选中状态。

该系统展示了如何使用Qt的图形框架和自定义控件实现复杂的场景管理。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部