You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Drone_project/Src/ui/mainwindow.cpp

675 lines
24 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "mainwindow.h"
#include "../models/dronedata.h"
#include "../models/detectiondata.h"
#include "../pages/videopage.h"
#include "../pages/mappage.h"
#include "../pages/datapage.h"
#include "../pages/visionmodelpage.h"
#include "../utils/stylehelper.h"
#include <QApplication>
#include <QStackedWidget>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
#include <QPushButton>
#include <QLabel>
#include <QGroupBox>
#include <QFrame>
#include <QLineEdit>
#include <QComboBox>
#include <QSpacerItem>
#include <QProgressBar>
#include <QGraphicsDropShadowEffect>
#include <QDebug> // Added for qDebug
#include <QScrollArea> // Added for QScrollArea
// 添加TaskDecisionPage包含
#include "../pages/taskdecisionpage.h"
#include "../pages/dronemanagementpage.h"
#include "../pages/taskdetailspage.h"
// 在文件顶部添加extern声明
// extern DroneManager* globalDroneManager;
// extern DetectionData* globalDetectionData;
// 改为定义
DroneManager* globalDroneManager = nullptr;
DetectionData* globalDetectionData = nullptr;
static QGroupBox* makeGroupBox(const QString& title, QWidget* inner) {
auto* gb = new QGroupBox(title);
auto* v = new QVBoxLayout(gb);
v->setContentsMargins(10,10,10,10);
v->addWidget(inner);
return gb;
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, droneManager_(new DroneManager(this))
, droneSelector_(nullptr)
, posXLabel_(nullptr), posYLabel_(nullptr), posZLabel_(nullptr)
, velXLabel_(nullptr), velYLabel_(nullptr), velZLabel_(nullptr)
, attRLabel_(nullptr), attPLabel_(nullptr), attYLabel_(nullptr)
, expXLabel_(nullptr), expYLabel_(nullptr), expZLabel_(nullptr)
, expVxLabel_(nullptr), expVyLabel_(nullptr), expVzLabel_(nullptr)
, videoInfoLabel_(nullptr)
, detectionTargets_(nullptr), detectionTargetObject_(nullptr), detectionAccuracy_(nullptr), detectionTime_(nullptr)
, detectionData_(new DetectionData(this))
// 初始化新成员
, baseFontSize_(10)
, initialWidth_(1200)
{
// 初始化无人机数据
initializeDrones();
// 顶部工具条
auto* header = buildHeader();
// 左侧侧边栏
auto* side = buildSideNav();
// 页面堆栈
pages_ = new QStackedWidget(this);
auto* pageMap = buildMapPage(); // 先地图
auto* pageVideo = buildVideoPage(); // 然后视频
auto* pageData = buildDataPage();
auto* pageDroneMgmt = buildDroneManagementPage();
auto* pageTask = buildTaskDecisionPage(); // 新页面
auto* pageTaskDetails = buildTaskDetailsPage();
auto* pageVision = buildVisionModelPage();
pages_->addWidget(pageMap);
pages_->addWidget(pageVideo);
pages_->addWidget(pageData);
pages_->addWidget(pageDroneMgmt);
pages_->addWidget(pageTask);
pages_->addWidget(pageTaskDetails);
pages_->addWidget(pageVision);
// 右侧状态信息(两页共用静态占位)
rightPanel_ = buildRightStatusPanel();
rightPanel_->setMinimumWidth(260);
// 中间主体
auto* centerWidget = new QWidget(this);
auto* centerV = new QVBoxLayout(centerWidget);
centerV->setContentsMargins(8,8,8,8);
centerV->setSpacing(8);
centerV->addWidget(header);
auto* contentH = new QHBoxLayout();
contentH->setSpacing(8);
contentH->addWidget(side);
contentH->addWidget(pages_, 1);
contentH->addWidget(rightPanel_);
centerV->addLayout(contentH, 1);
setCentralWidget(centerWidget);
setWindowTitle("");
// 设置初始大小(用于缩放计算)
resize(1200, 800); // 假设初始大小,您可以调整
// 连接信号槽
connect(droneManager_, &DroneManager::currentDroneChanged,
this, &MainWindow::onCurrentDroneChanged);
// 连接检测数据信号
connect(detectionData_, &DetectionData::detectionUpdated,
this, &MainWindow::updateDetectionInfo);
// 启动检测模拟
// detectionData_->startSimulation();
globalDroneManager = droneManager_;
globalDetectionData = detectionData_;
// 连接信号到DataPage
DataPage* dataPage = qobject_cast<DataPage*>(pages_->widget(2));
if (dataPage) {
connect(droneManager_, &DroneManager::currentDroneChanged, dataPage, &DataPage::updateDroneInfo);
connect(detectionData_, &DetectionData::detectionUpdated, dataPage, &DataPage::updateTargetInfo);
}
}
// 增强resizeEvent来调整所有收集的组件
void MainWindow::resizeEvent(QResizeEvent *event) {
QMainWindow::resizeEvent(event);
// 移除所有设置以防止无限resize循环
// 只计算scale用于调试
float scale = static_cast<float>(width()) / initialWidth_;
qDebug() << "MainWindow resized with scale:" << scale;
}
QWidget* MainWindow::buildHeader() {
auto* w = new QWidget(this);
w->setObjectName(QString("headerBar"));
auto* h = new QHBoxLayout(w);
h->setContentsMargins(10,6,10,6);
h->setSpacing(12);
auto* logo = new QLabel("基于无人机的察打一体地面指挥端");
logo->setStyleSheet("font-weight:bold; font-size:16px;");
h->addWidget(logo);
h->addSpacing(20);
h->addStretch(1);
// 在buildHeader中收集头部按钮
for (auto text : {"连接设置"}) {
auto* b = new QPushButton(text);
b->setProperty("primary", true);
h->addWidget(b);
headerButtons_.append(b);
}
auto* rec = new QLabel(" ");
rec->setFixedSize(14,14);
rec->setObjectName(QString("recLed"));
h->addWidget(rec);
// 阴影
auto* shadow = new QGraphicsDropShadowEffect(w);
shadow->setBlurRadius(18);
shadow->setOffset(0, 2);
shadow->setColor(QColor(0,0,0,30));
w->setGraphicsEffect(shadow);
return w;
}
QWidget* MainWindow::buildSideNav() {
auto* side = new QWidget(this);
// side->setFixedWidth(76); // 移除固定宽度,让它可调整
side->setObjectName(QString("sideNav"));
auto* v = new QVBoxLayout(side);
v->setContentsMargins(6,8,6,8);
v->setSpacing(10);
// 在buildSideNav中收集侧边栏按钮
auto makeBtn = [&](const QString& text, auto slot){
auto* b = new QToolButton();
b->setText(text);
b->setToolButtonStyle(Qt::ToolButtonTextOnly);
b->setFixedHeight(48);
connect(b, &QToolButton::clicked, this, slot);
v->addWidget(b);
sideNavButtons_.append(b); // 添加到列表
};
// 在buildSideNav中调整槽连接以交换内容
makeBtn("视频监控", &MainWindow::showMapPage); // 显示原地图内容
makeBtn("地图监控", &MainWindow::showVideoPage); // 显示原视频内容
makeBtn("数据监控", &MainWindow::showDataPage);
makeBtn("无人机管理", &MainWindow::showDroneManagementPage);
makeBtn("任务决策", &MainWindow::showTaskDecisionPage);
makeBtn("任务详情", &MainWindow::showTaskDetailsPage);
makeBtn("视觉模型", &MainWindow::showVisionModelPage);
v->addStretch(1);
auto* shadow = new QGraphicsDropShadowEffect(side);
shadow->setBlurRadius(18);
shadow->setOffset(0, 2);
shadow->setColor(QColor(0,0,0,24));
side->setGraphicsEffect(shadow);
return side;
}
QWidget* MainWindow::buildVideoPage() {
// 左图风格:中间大区域 + 底部控制条
auto* page = new QWidget(this);
auto* v = new QVBoxLayout(page);
v->setSpacing(8);
v->setContentsMargins(0,0,0,0);
// 顶部无人机选择区域
auto* topBar = new QWidget(page);
auto* th = new QHBoxLayout(topBar);
th->setContentsMargins(0,0,0,0);
th->setSpacing(12);
auto* droneLabel = new QLabel("选择无人机:");
droneLabel->setStyleSheet("font-weight:bold;");
th->addWidget(droneLabel);
droneSelector_ = new QComboBox(page);
droneSelector_->setFixedWidth(150);
droneSelector_->setObjectName("droneSelector");
// 从无人机管理器获取无人机列表
QStringList droneIds = droneManager_->getDroneIds();
for (const QString& id : droneIds) {
DroneData* drone = droneManager_->getDrone(id);
if (drone) {
droneSelector_->addItem(drone->getName(), id);
}
}
// 连接选择变化信号
connect(droneSelector_, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::onDroneSelectionChanged);
th->addWidget(droneSelector_);
th->addStretch(1);
// 连接状态指示器
auto* statusLabel = new QLabel("● 已连接");
statusLabel->setStyleSheet("color:#4caf50; font-weight:bold;");
th->addWidget(statusLabel);
v->addWidget(topBar);
// 中间黑色占位(视频/地图区域)
auto* center = new QFrame(page);
center->setStyleSheet("QFrame{background:#2b2b2b; border:1px solid #444;}");
center->setMinimumHeight(520);
// 在视频区域添加当前无人机信息显示
videoInfoLabel_ = new QLabel("当前监控: 无人机-001");
videoInfoLabel_->setStyleSheet("color:#ffffff; font-size:16px; font-weight:bold; background:rgba(0,0,0,0.3); padding:8px; border-radius:4px;");
videoInfoLabel_->setAlignment(Qt::AlignCenter);
videoInfoLabel_->setObjectName("videoInfoLabel");
// 将信息标签添加到视频区域中心
auto* centerLayout = new QVBoxLayout(center);
centerLayout->setContentsMargins(0,0,0,0);
centerLayout->addStretch(1);
centerLayout->addWidget(videoInfoLabel_);
centerLayout->addStretch(1);
// 底部条(交换为原地图页的播放控制)
auto* bottom = new QWidget(page);
auto* bh = new QHBoxLayout(bottom);
bh->setContentsMargins(0,0,0,0);
for (auto text : {"播放", "暂停", "拍照(T)", "录像(R)", "停止", "框选", "点击", "手动控制"}) {
bh->addWidget(new QPushButton(text));
}
bh->addStretch(1);
// 检测信息对话框
auto* detectionDialog = new QFrame(page);
detectionDialog->setStyleSheet("QFrame{background:#f8f9fa; border:1px solid #dee2e6; border-radius:8px; margin:4px;}");
detectionDialog->setMaximumHeight(120);
auto* detectionLayout = new QVBoxLayout(detectionDialog);
detectionLayout->setContentsMargins(12,8,12,8);
detectionLayout->setSpacing(6);
// 检测信息标题
auto* detectionTitle = new QLabel("实时检测信息");
detectionTitle->setStyleSheet("font-weight:bold; color:#495057; font-size:14px;");
detectionLayout->addWidget(detectionTitle);
// 检测信息内容区域
auto* detectionContent = new QWidget();
auto* contentLayout = new QHBoxLayout(detectionContent);
contentLayout->setContentsMargins(0,0,0,0);
contentLayout->setSpacing(20);
// 检测目标信息
auto* targetInfo = new QWidget();
auto* targetLayout = new QVBoxLayout(targetInfo);
targetLayout->setContentsMargins(0,0,0,0);
targetLayout->setSpacing(4);
auto* targetLabel = new QLabel("检测目标:");
targetLabel->setStyleSheet("font-weight:bold; color:#6c757d;");
detectionTargets_ = new QLabel("人员 × 3, 车辆 × 2");
detectionTargets_->setStyleSheet("color:#28a745; font-weight:bold;");
detectionTargets_->setObjectName("detectionTargets");
targetLayout->addWidget(targetLabel);
targetLayout->addWidget(detectionTargets_);
// 目标对象信息
auto* targetObjectInfo = new QWidget();
auto* targetObjectLayout = new QVBoxLayout(targetObjectInfo);
targetObjectLayout->setContentsMargins(0,0,0,0);
targetObjectLayout->setSpacing(4);
auto* targetObjectLabel = new QLabel("是否为目标对象:");
targetObjectLabel->setStyleSheet("font-weight:bold; color:#6c757d;");
detectionTargetObject_ = new QLabel("● 是");
detectionTargetObject_->setStyleSheet("color:#28a745; font-weight:bold;");
detectionTargetObject_->setObjectName("detectionTargetObject");
targetObjectLayout->addWidget(targetObjectLabel);
targetObjectLayout->addWidget(detectionTargetObject_);
// 检测精度信息
auto* accuracyInfo = new QWidget();
auto* accuracyLayout = new QVBoxLayout(accuracyInfo);
accuracyLayout->setContentsMargins(0,0,0,0);
accuracyLayout->setSpacing(4);
auto* accuracyLabel = new QLabel("检测精度:");
accuracyLabel->setStyleSheet("font-weight:bold; color:#6c757d;");
detectionAccuracy_ = new QLabel("95.2%");
detectionAccuracy_->setStyleSheet("color:#fd7e14; font-weight:bold;");
detectionAccuracy_->setObjectName("detectionAccuracy");
accuracyLayout->addWidget(accuracyLabel);
accuracyLayout->addWidget(detectionAccuracy_);
// 检测时间信息
auto* timeInfo = new QWidget();
auto* timeLayout = new QVBoxLayout(timeInfo);
timeLayout->setContentsMargins(0,0,0,0);
timeLayout->setSpacing(4);
auto* timeLabel = new QLabel("最后更新:");
timeLabel->setStyleSheet("font-weight:bold; color:#6c757d;");
detectionTime_ = new QLabel("2024-01-15 14:32:15");
detectionTime_->setStyleSheet("color:#6c757d;");
detectionTime_->setObjectName("detectionTime");
timeLayout->addWidget(timeLabel);
timeLayout->addWidget(detectionTime_);
contentLayout->addWidget(targetInfo);
contentLayout->addWidget(targetObjectInfo);
contentLayout->addWidget(accuracyInfo);
contentLayout->addWidget(timeInfo);
contentLayout->addStretch(1);
detectionLayout->addWidget(detectionContent);
v->addWidget(center, 1);
v->addWidget(bottom);
v->addWidget(detectionDialog);
return page;
}
QWidget* MainWindow::buildMapPage() {
return new MapPage(this);
}
QWidget* MainWindow::buildRightStatusPanel() {
auto* panel = new QWidget(this);
panel->setObjectName(QString("rightPanel"));
auto* v = new QVBoxLayout(panel);
v->setSpacing(8);
v->setContentsMargins(0,0,0,0);
// 基本信息 / GPS信息 标签页视觉(简化为两个分组)
auto makeKV = [this](const QString& k, QLabel** labelRef) {
auto* row = new QWidget();
auto* h = new QHBoxLayout(row);
h->setContentsMargins(0,0,0,0);
h->addWidget(new QLabel(k));
auto* val = new QLabel("0.00");
val->setAlignment(Qt::AlignRight);
*labelRef = val; // 保存标签引用
h->addWidget(val);
return row;
};
auto* baseInfo = new QWidget();
auto* bi = new QVBoxLayout(baseInfo);
bi->setContentsMargins(0,0,0,0);
bi->addWidget(new QLabel("位置[x y z] [m]"));
bi->addWidget(makeKV("x:", &posXLabel_));
bi->addWidget(makeKV("y:", &posYLabel_));
bi->addWidget(makeKV("z:", &posZLabel_));
bi->addSpacing(6);
bi->addWidget(new QLabel("速度[x y z] [m/s]"));
bi->addWidget(makeKV("vx:", &velXLabel_));
bi->addWidget(makeKV("vy:", &velYLabel_));
bi->addWidget(makeKV("vz:", &velZLabel_));
bi->addSpacing(6);
bi->addWidget(new QLabel("姿态[r p y] [deg]"));
bi->addWidget(makeKV("r:", &attRLabel_));
bi->addWidget(makeKV("p:", &attPLabel_));
bi->addWidget(makeKV("y:", &attYLabel_));
v->addWidget(makeGroupBox("基本信息", baseInfo));
auto* expectInfo = new QWidget();
auto* ei = new QVBoxLayout(expectInfo);
ei->setContentsMargins(0,0,0,0);
ei->addWidget(new QLabel("期望位置[x y z] [m]"));
ei->addWidget(makeKV("ex:", &expXLabel_));
ei->addWidget(makeKV("ey:", &expYLabel_));
ei->addWidget(makeKV("ez:", &expZLabel_));
ei->addSpacing(6);
ei->addWidget(new QLabel("期望速度[x y z] [m/s]"));
ei->addWidget(makeKV("evx:", &expVxLabel_));
ei->addWidget(makeKV("evy:", &expVyLabel_));
ei->addWidget(makeKV("evz:", &expVzLabel_));
v->addWidget(makeGroupBox("期望信息", expectInfo));
// 右侧按钮区域(当前悬停等)
auto* act = new QWidget();
auto* av = new QVBoxLayout(act);
for (auto text : {"当前点悬停", "初始化悬停", "删除"}) {
auto* b = new QPushButton(text);
b->setProperty("primary", true);
av->addWidget(b);
rightPanelButtons_.append(b); // 添加到列表
}
av->addSpacing(8);
auto* mode = new QComboBox();
mode->addItems({"XYZ_POS", "XYZ_POS_YAW", "VEL", "ACC"});
av->addWidget(mode);
rightPanelModeCombo_ = mode; // 保存引用
for (auto k : {"x [m]", "y [m]", "z [m]", "yaw [deg]"}) {
auto* e = new QLineEdit();
e->setPlaceholderText(k);
av->addWidget(e);
rightPanelInputs_.append(e); // 添加到列表
}
auto* upload = new QPushButton("上传");
upload->setProperty("primary", true);
av->addWidget(upload);
rightPanelButtons_.append(upload); // 添加到列表
av->addStretch(1);
// 阴影
auto* shadow = new QGraphicsDropShadowEffect(panel);
shadow->setBlurRadius(18);
shadow->setOffset(0, 2);
shadow->setColor(QColor(0,0,0,16));
panel->setGraphicsEffect(shadow);
// 使用QScrollArea包裹act以防溢出
auto* scrollArea = new QScrollArea(panel);
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(act);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
v->addWidget(scrollArea, 1); // 替换原v->addWidget(act);
return panel;
}
void MainWindow::showVideoPage() { pages_->setCurrentIndex(0); }
void MainWindow::showMapPage() { pages_->setCurrentIndex(1); }
void MainWindow::showDataPage() { pages_->setCurrentIndex(2); }
void MainWindow::showDroneManagementPage() { pages_->setCurrentIndex(3); }
void MainWindow::showTaskDecisionPage() { pages_->setCurrentIndex(4); }
void MainWindow::showTaskDetailsPage() { pages_->setCurrentIndex(5); }
void MainWindow::showVisionModelPage() { pages_->setCurrentIndex(6); }
QWidget* MainWindow::buildDataPage() {
return new DataPage(this); // 使用DataPage类
}
QWidget* MainWindow::buildTaskDecisionPage() {
return new TaskDecisionPage(this); // 使用新类
}
QWidget* MainWindow::buildDroneManagementPage() {
return new DroneManagementPage(this);
}
QWidget* MainWindow::buildTaskDetailsPage() {
return new TaskDetailsPage(this);
}
QWidget* MainWindow::buildVisionModelPage() {
// 使用我们集成了YOLOv5功能的VisionModelPage类
auto* page = new VisionModelPage(this);
return page;
}
// 初始化无人机数据
void MainWindow::initializeDrones() {
// 添加4架无人机
droneManager_->addDrone("drone-001", "无人机-001");
droneManager_->addDrone("drone-002", "无人机-002");
droneManager_->addDrone("drone-003", "无人机-003");
droneManager_->addDrone("drone-004", "无人机-004");
// 设置第一架为当前选中
if (!droneManager_->getDroneIds().isEmpty()) {
droneManager_->setCurrentDrone(droneManager_->getDroneIds().first());
}
}
// 无人机选择变化处理
void MainWindow::onDroneSelectionChanged() {
if (!droneSelector_) return;
int index = droneSelector_->currentIndex();
if (index >= 0) {
QString droneId = droneSelector_->itemData(index).toString();
droneManager_->setCurrentDrone(droneId);
}
}
// 当前无人机变化处理
void MainWindow::onCurrentDroneChanged(const QString& droneId) {
if (!droneSelector_) return;
// 更新下拉框选择
for (int i = 0; i < droneSelector_->count(); ++i) {
if (droneSelector_->itemData(i).toString() == droneId) {
droneSelector_->setCurrentIndex(i);
break;
}
}
// 连接当前无人机的数据更新信号
DroneData* currentDrone = droneManager_->getCurrentDrone();
if (currentDrone) {
connect(currentDrone, &DroneData::dataChanged,
this, &MainWindow::updateDroneStatus, Qt::UniqueConnection);
updateDroneStatus(); // 立即更新一次
}
}
// 更新无人机状态显示
void MainWindow::updateDroneStatus() {
DroneData* currentDrone = droneManager_->getCurrentDrone();
if (!currentDrone) return;
// 更新视频区域显示信息
if (videoInfoLabel_) {
videoInfoLabel_->setText(QString("当前监控: %1").arg(currentDrone->getName()));
}
// 更新位置信息
QVector3D pos = currentDrone->getPosition();
if (posXLabel_) posXLabel_->setText(QString::number(pos.x(), 'f', 2));
if (posYLabel_) posYLabel_->setText(QString::number(pos.y(), 'f', 2));
if (posZLabel_) posZLabel_->setText(QString::number(pos.z(), 'f', 2));
// 更新速度信息
QVector3D vel = currentDrone->getVelocity();
if (velXLabel_) velXLabel_->setText(QString::number(vel.x(), 'f', 2));
if (velYLabel_) velYLabel_->setText(QString::number(vel.y(), 'f', 2));
if (velZLabel_) velZLabel_->setText(QString::number(vel.z(), 'f', 2));
// 更新姿态信息
QVector3D att = currentDrone->getAttitude();
if (attRLabel_) attRLabel_->setText(QString::number(att.x(), 'f', 2));
if (attPLabel_) attPLabel_->setText(QString::number(att.y(), 'f', 2));
if (attYLabel_) attYLabel_->setText(QString::number(att.z(), 'f', 2));
// 更新期望位置信息
QVector3D expPos = currentDrone->getExpectedPosition();
if (expXLabel_) expXLabel_->setText(QString::number(expPos.x(), 'f', 2));
if (expYLabel_) expYLabel_->setText(QString::number(expPos.y(), 'f', 2));
if (expZLabel_) expZLabel_->setText(QString::number(expPos.z(), 'f', 2));
// 更新期望速度信息
QVector3D expVel = currentDrone->getExpectedVelocity();
if (expVxLabel_) expVxLabel_->setText(QString::number(expVel.x(), 'f', 2));
if (expVyLabel_) expVyLabel_->setText(QString::number(expVel.y(), 'f', 2));
if (expVzLabel_) expVzLabel_->setText(QString::number(expVel.z(), 'f', 2));
}
// 更新检测信息显示
void MainWindow::updateDetectionInfo() {
if (!detectionData_) return;
// 更新检测目标信息
if (detectionTargets_) {
QVector<DetectionTarget> targets = detectionData_->getTargets();
QStringList targetCounts;
// 统计各类型目标数量
QMap<QString, int> typeCount;
for (const auto& target : targets) {
typeCount[target.type]++;
}
// 生成目标描述文本
for (auto it = typeCount.begin(); it != typeCount.end(); ++it) {
targetCounts.append(QString("%1 × %2").arg(it.key()).arg(it.value()));
}
if (targetCounts.isEmpty()) {
detectionTargets_->setText("无检测目标");
detectionTargets_->setStyleSheet("color:#6c757d; font-weight:bold;");
} else {
detectionTargets_->setText(targetCounts.join(", "));
detectionTargets_->setStyleSheet("color:#28a745; font-weight:bold;");
}
}
// 更新目标对象信息
if (detectionTargetObject_) {
QVector<DetectionTarget> targets = detectionData_->getTargets();
bool hasTargets = !targets.isEmpty();
if (hasTargets) {
detectionTargetObject_->setText("● 是");
detectionTargetObject_->setStyleSheet("color:#28a745; font-weight:bold;");
} else {
detectionTargetObject_->setText("● 否");
detectionTargetObject_->setStyleSheet("color:#6c757d; font-weight:bold;");
}
}
// 更新检测精度
if (detectionAccuracy_) {
float accuracy = detectionData_->getAccuracy();
detectionAccuracy_->setText(QString("%1%").arg(accuracy, 0, 'f', 1));
// 根据精度设置颜色
QString color;
if (accuracy >= 90.0f) {
color = "#28a745";
} else if (accuracy >= 80.0f) {
color = "#fd7e14";
} else {
color = "#dc3545";
}
detectionAccuracy_->setStyleSheet(QString("color:%1; font-weight:bold;").arg(color));
}
// 更新最后更新时间
if (detectionTime_) {
QDateTime lastUpdate = detectionData_->getLastUpdate();
detectionTime_->setText(lastUpdate.toString("yyyy-MM-dd hh:mm:ss"));
}
}