#include "mainwindow.h" #include "ui_mainwindow.h" #include "resultitem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "VrLog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 设置状态栏字体 QFont statusFont = statusBar()->font(); statusFont.setPointSize(12); statusBar()->setFont(statusFont); // 设置状态栏颜色和padding statusBar()->setStyleSheet("QStatusBar { color: rgb(239, 241, 245); padding: 20px; }"); // 启动后自动全屏显示 this->showFullScreen(); // 初始化GraphicsScene QGraphicsScene* scene = new QGraphicsScene(this); ui->detect_image->setScene(scene); // 初始化日志模型 m_logModel = new QStringListModel(this); ui->detect_log->setModel(m_logModel); // 原有的状态指示器已删除,状态显示统一在devstatus中处理 // 连接工作状态更新信号槽 connect(this, &MainWindow::workStatusUpdateRequested, this, &MainWindow::updateWorkStatusLabel); // 连接检测结果更新信号槽 connect(this, &MainWindow::detectionResultUpdateRequested, this, &MainWindow::updateDetectionResultDisplay); // 连接日志更新信号槽 connect(this, &MainWindow::logUpdateRequested, this, &MainWindow::updateDetectionLog); // 连接清空日志信号槽 connect(this, &MainWindow::logClearRequested, this, &MainWindow::clearDetectionLogUI); updateStatusLog(tr("设备开始初始化...")); // 初始化模块 Init(); } MainWindow::~MainWindow() { // 释放业务逻辑处理类 if (m_presenter) { delete m_presenter; m_presenter = nullptr; } delete ui; } void MainWindow::updateStatusLog(const QString& message) { // 更新状态栏 // statusBar()->showMessage(message); // 通过信号槽机制更新detect_log控件 emit logUpdateRequested(message); } void MainWindow::clearDetectionLog() { // 通过信号槽机制清空日志 emit logClearRequested(); } void MainWindow::Init() { // 创建业务逻辑处理类 m_presenter = new GrabBagPresenter(); // 设置状态回调接口 m_presenter->SetStatusCallback(this); m_deviceStatusWidget = new devstatus(); //因为初始化回调的数据要存储,所以要在init前创建好 // 初始化业务逻辑 int result = m_presenter->Init(); if (result != 0) { updateStatusLog(tr("初始化失败,错误码:%1").arg(result)); } // 初始化完成后,在detect_result_list中增加设备状态widget QListWidgetItem* deviceStatusItem = new QListWidgetItem(); deviceStatusItem->setBackground(QBrush(Qt::transparent)); deviceStatusItem->setSizeHint(QSize(272, 200)); ui->detect_result_list->addItem(deviceStatusItem); ui->detect_result_list->setItemWidget(deviceStatusItem, m_deviceStatusWidget); // 设置列表视图模式 ui->detect_result_list->setViewMode(QListView::IconMode); ui->detect_result_list->setResizeMode(QListView::Adjust); ui->detect_result_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); ui->detect_result_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } void MainWindow::displayImage(const QImage& image) { if (image.isNull()) { updateStatusLog(tr("图片无效")); return; } QGraphicsScene* scene = ui->detect_image->scene(); scene->clear(); QPixmap pixmap = QPixmap::fromImage(image); scene->addPixmap(pixmap); ui->detect_image->fitInView(scene->sceneRect(), Qt::KeepAspectRatio); } // 添加扩展版本的检测结果函数 void MainWindow::addDetectionResult(const DetectionResult& result) { // 清空之前的数据(除了第一个设备状态item) while (ui->detect_result_list->count() > 1) { QListWidgetItem* item = ui->detect_result_list->takeItem(1); delete item; } // 更新现有设备状态显示(第一个item就是设备状态) if (m_deviceStatusWidget) { // m_deviceStatusWidget会自动从其内部状态获取设备状态信息 // 不需要手动更新,因为状态变化时会直接更新到widget中 } // 设置为图标模式,实现网格布局(多列显示) ui->detect_result_list->setViewMode(QListView::IconMode); ui->detect_result_list->setResizeMode(QListView::Adjust); // 设置滚动条策略:始终显示垂直滚动条,隐藏水平滚动条 ui->detect_result_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); ui->detect_result_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // 计算gridWidth:考虑12px间距,确保两列布局 int totalWidth = ui->detect_result_list->width(); int itemSpacing = 12; int gridWidth = (totalWidth - itemSpacing - 17) / 2; //20是滚动条的宽度 int gridHeight = 200; ui->detect_result_list->setGridSize(QSize(gridWidth, gridHeight)); // 设置每个格子的大小 ui->detect_result_list->setSpacing(itemSpacing); // 设置item间距为12px ui->detect_result_list->setFlow(QListView::LeftToRight); // 从左到右排列 ui->detect_result_list->setWrapping(true); // 允许换行 auto layoutIter = result.positionLayout.begin(); int targetIndex = 1; while(layoutIter != result.positionLayout.end()) { auto positionIter = layoutIter->position.begin(); while(positionIter != layoutIter->position.end()) { // 创建自定义的ResultItem widget ResultItem* resultWidget = new ResultItem(); // 设置widget的autoFillBackground属性,确保背景色生效 resultWidget->setAutoFillBackground(true); // 设置检测结果数据,直接使用GrabBagPosition resultWidget->setResultData(targetIndex, *positionIter); // 创建QListWidgetItem QListWidgetItem* item = new QListWidgetItem(); // 设置item背景为透明,让自定义widget的背景显示出来 item->setBackground(QBrush(Qt::transparent)); // 设置item的大小提示 - 应该与gridSize一致 item->setSizeHint(QSize(gridWidth, gridHeight)); // 将item添加到列表 ui->detect_result_list->addItem(item); // 将自定义widget设置为item的显示内容 ui->detect_result_list->setItemWidget(item, resultWidget); targetIndex++; positionIter++; } layoutIter++; } } // 状态更新槽函数 void MainWindow::OnStatusUpdate(const std::string& statusMessage) { LOG_DEBUG("[UI Display] Status update: %s\n", statusMessage.c_str()); updateStatusLog(QString::fromStdString(statusMessage)); } void MainWindow::OnDetectionResult(const DetectionResult& result) { // 通过信号槽机制更新UI(确保在主线程中执行) emit detectionResultUpdateRequested(result); } void MainWindow::OnCamera1StatusChanged(bool isConnected) { // 直接更新设备状态widget if (m_deviceStatusWidget) { m_deviceStatusWidget->updateCamera1Status(isConnected); } } // 相机2状态更新槽函数 void MainWindow::OnCamera2StatusChanged(bool isConnected) { // 直接更新设备状态widget if (m_deviceStatusWidget) { m_deviceStatusWidget->updateCamera2Status(isConnected); } } // 相机个数更新槽函数 void MainWindow::OnCameraCountChanged(int cameraCount) { // 设置设备状态widget中的相机数量 if (m_deviceStatusWidget) { m_deviceStatusWidget->setCameraCount(cameraCount); } // 如果只有一个相机,更新状态消息 if (cameraCount < 2) { // 更新状态消息 updateStatusLog(tr("系统使用单相机模式")); } else { // 更新状态消息 updateStatusLog(tr("系统使用双相机模式")); } } // 机械臂状态更新槽函数 void MainWindow::OnRobotConnectionChanged(bool isConnected) { // 直接更新设备状态widget if (m_deviceStatusWidget) { m_deviceStatusWidget->updateRobotStatus(isConnected); } } // 工作状态更新槽函数 void MainWindow::OnWorkStatusChanged(WorkStatus status) { // 通过信号槽机制更新UI(确保在主线程中执行) emit workStatusUpdateRequested(status); } void MainWindow::updateWorkStatusLabel(WorkStatus status) { // 如果状态变为Working,清空检测日志(表示开始新的检测) if (status == WorkStatus::Working) { clearDetectionLog(); } // 获取状态对应的显示文本 QString statusText = QString::fromStdString(WorkStatusToString(status)); // 在label_work中显示状态 if (ui->label_work) { ui->label_work->setText(statusText); // 根据不同状态设置不同的样式 switch (status) { case WorkStatus::Ready: ui->label_work->setStyleSheet("color: green;"); break; case WorkStatus::Working: ui->label_work->setStyleSheet("color: blue;"); break; case WorkStatus::Completed: ui->label_work->setStyleSheet("color: green; font-weight: bold;"); break; case WorkStatus::Error: ui->label_work->setStyleSheet("color: red; font-weight: bold;"); break; default: ui->label_work->setStyleSheet(""); break; } } } void MainWindow::updateDetectionResultDisplay(const DetectionResult& result) { // 显示检测图像 displayImage(result.image); // 更新检测结果到列表 addDetectionResult(result); } void MainWindow::updateDetectionLog(const QString& message) { // 在UI线程中更新detect_log控件(QListView) if (!m_logModel) return ; // 添加时间戳(包含年月日) QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); QString logEntry = QString("[%1] %2").arg(timestamp).arg(message); // 获取当前数据 QStringList logList = m_logModel->stringList(); // 添加新的日志条目 logList.append(logEntry); // 更新模型 m_logModel->setStringList(logList); // 自动滚动到最底部 QModelIndex lastIndex = m_logModel->index(logList.size() - 1); ui->detect_log->scrollTo(lastIndex); } void MainWindow::clearDetectionLogUI() { // 在UI线程中清空检测日志 if (m_logModel) { m_logModel->setStringList(QStringList()); } } void MainWindow::on_action_tool_debug_data_triggered() { // 打开文件选择对话框 QString fileName = QFileDialog::getOpenFileName( this, tr("选择调试数据文件"), QString(), tr("激光数据文件 (*.txt);;所有文件 (*.*)") ); if (fileName.isEmpty()) { // 用户取消了文件选择 return; } // 检查Presenter是否已初始化 if (!m_presenter) { QMessageBox::warning(this, tr("错误"), tr("系统未正确初始化!")); return; } // 清空检测日志,开始新的检测 clearDetectionLog(); std::thread t([this, fileName]() { updateStatusLog(tr("正在加载调试数据文件: %1").arg(fileName)); int result = m_presenter->LoadDebugDataAndDetect(fileName.toStdString()); if (result == 0) { updateStatusLog(tr("调试数据加载和检测成功")); } else { QString errorMsg = tr("调试数据加载失败,错误码: %1").arg(result); updateStatusLog(errorMsg); QMessageBox::warning(this, tr("错误"), errorMsg); } }); t.detach(); } void MainWindow::on_btn_start_clicked() { // 清空检测日志,开始新的检测 clearDetectionLog(); // 使用Presenter启动检测 if (m_presenter) { m_presenter->StartDetection(); } } void MainWindow::on_btn_stop_clicked() { if (m_presenter) { m_presenter->StopDetection(); } } void MainWindow::on_btn_camera_clicked() { IVrEyeDevice* pDevice = m_presenter->GetEyeDevice(0); if(nullptr == pDevice){ QMessageBox::warning(this, "设备错误", "相机设备未正确初始化!"); return; } if(nullptr == ui_dialogCamera){ ui_dialogCamera = new DialogCamera(pDevice, this); } ui_dialogCamera->show(); } void MainWindow::on_btn_algo_config_clicked() { if(nullptr == ui_dialogConfig){ ui_dialogConfig = new DialogConfig; } ui_dialogConfig->show(); } void MainWindow::on_btn_camera_levelling_clicked() { }