2025-06-08 12:48:04 +08:00
|
|
|
|
#include "mainwindow.h"
|
|
|
|
|
|
#include "ui_mainwindow.h"
|
|
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
|
|
#include <QStandardItemModel>
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
|
#include <QBrush>
|
2025-06-08 23:51:48 +08:00
|
|
|
|
#include <QMessageBox>
|
2025-06-08 12:48:04 +08:00
|
|
|
|
|
|
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
|
|
|
|
: QMainWindow(parent)
|
|
|
|
|
|
, ui(new Ui::MainWindow)
|
|
|
|
|
|
{
|
|
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置状态栏字体
|
|
|
|
|
|
QFont statusFont = statusBar()->font();
|
|
|
|
|
|
statusFont.setPointSize(18);
|
|
|
|
|
|
statusBar()->setFont(statusFont);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置按钮图标
|
|
|
|
|
|
ui->btn_start->setIcon(QIcon(":/resource/start.png"));
|
|
|
|
|
|
ui->btn_start->setIconSize(QSize(32, 32));
|
|
|
|
|
|
ui->btn_stop->setIcon(QIcon(":/resource/stop.png"));
|
|
|
|
|
|
ui->btn_stop->setIconSize(QSize(32, 32));
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化GraphicsScene
|
|
|
|
|
|
QGraphicsScene* scene = new QGraphicsScene(this);
|
|
|
|
|
|
ui->detect_image->setScene(scene);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化ListView的Model
|
|
|
|
|
|
QStandardItemModel* model = new QStandardItemModel(this);
|
|
|
|
|
|
ui->detect_result->setModel(model);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置label前圆点(在线/离线)
|
|
|
|
|
|
setStatusDot(ui->label_camera_1_status, false); // 在线绿色
|
|
|
|
|
|
setStatusDot(ui->label_camera_2_status, false); // 在线绿色
|
|
|
|
|
|
setStatusDot(ui->label_robot_status, false); // 在线绿色
|
2025-06-08 23:51:48 +08:00
|
|
|
|
|
2025-06-08 12:48:04 +08:00
|
|
|
|
// 连接菜单信号
|
2025-06-08 23:51:48 +08:00
|
|
|
|
// connect(ui->menu_camera, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_triggered);
|
|
|
|
|
|
// connect(ui->menu_config, &QMenu::aboutToShow, this, &MainWindow::on_menu_config_triggered);
|
|
|
|
|
|
// connect(ui->menu_camera_adjust, &QMenu::aboutToShow, this, &MainWindow::on_menu_camera_adjust_triggered);
|
|
|
|
|
|
|
|
|
|
|
|
// 连接工作状态更新信号槽
|
|
|
|
|
|
connect(this, &MainWindow::workStatusUpdateRequested, this, &MainWindow::updateWorkStatusLabel);
|
|
|
|
|
|
|
|
|
|
|
|
// 连接检测结果更新信号槽
|
|
|
|
|
|
connect(this, &MainWindow::detectionResultUpdateRequested, this, &MainWindow::updateDetectionResultDisplay);
|
2025-06-08 12:48:04 +08:00
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::Init()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 创建业务逻辑处理类
|
|
|
|
|
|
m_presenter = new GrabBagPresenter();
|
|
|
|
|
|
|
|
|
|
|
|
// 设置状态回调接口
|
|
|
|
|
|
m_presenter->SetStatusCallback(this);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化业务逻辑
|
|
|
|
|
|
int result = m_presenter->Init();
|
|
|
|
|
|
if (result != 0) {
|
|
|
|
|
|
updateStatusLog(tr("初始化失败,错误码:%1").arg(result));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
auto layoutIter = result.positionLayout.begin();
|
|
|
|
|
|
|
|
|
|
|
|
while(layoutIter != result.positionLayout.end())
|
|
|
|
|
|
{
|
|
|
|
|
|
QString posStr = QString("\n第%1层\n").arg(layoutIter->layerIndex);
|
|
|
|
|
|
auto positionIter = layoutIter->position.begin();
|
|
|
|
|
|
while(positionIter != layoutIter->position.end())
|
|
|
|
|
|
{
|
|
|
|
|
|
posStr += QString("坐标: X=%1\n坐标: Y=%2\n坐标: Z=%3\n旋转: RZ=%4\n")
|
|
|
|
|
|
.arg(positionIter->x, 0, 'f', 2)
|
|
|
|
|
|
.arg(positionIter->y, 0, 'f', 2)
|
|
|
|
|
|
.arg(positionIter->z, 0, 'f', 2)
|
|
|
|
|
|
.arg(positionIter->yaw, 0, 'f', 2);
|
|
|
|
|
|
positionIter++;
|
|
|
|
|
|
}
|
|
|
|
|
|
layoutIter++;
|
|
|
|
|
|
QStandardItemModel* model = qobject_cast<QStandardItemModel*>(ui->detect_result->model());
|
|
|
|
|
|
if (model) {
|
|
|
|
|
|
QStandardItem* item = new QStandardItem(posStr);
|
|
|
|
|
|
model->appendRow(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setStatusDot实现移到MainWindow类作用域内
|
|
|
|
|
|
void MainWindow::setStatusDot(QLabel* label, bool isOnline) {
|
|
|
|
|
|
QPixmap dot(18, 18);
|
|
|
|
|
|
dot.fill(Qt::transparent);
|
|
|
|
|
|
QPainter painter(&dot);
|
|
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
|
|
|
|
QColor color = isOnline ? QColor(140, 180, 60) : QColor(220, 60, 60); // 绿色或红色
|
|
|
|
|
|
painter.setBrush(QBrush(color));
|
|
|
|
|
|
painter.setPen(Qt::NoPen);
|
|
|
|
|
|
painter.drawEllipse(0, 0, 18, 18);
|
|
|
|
|
|
painter.end();
|
|
|
|
|
|
label->setPixmap(dot);
|
|
|
|
|
|
label->setScaledContents(true);
|
|
|
|
|
|
label->setFixedSize(18, 18);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_btn_camera_clicked()
|
|
|
|
|
|
{
|
2025-06-08 23:51:48 +08:00
|
|
|
|
// if(nullptr == ui_dialogCamera){
|
|
|
|
|
|
// ui_dialogCamera = new DialogCamera;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ui_dialogCamera->show();
|
2025-06-08 12:48:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_btn_config_clicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(nullptr == ui_dialogConfig){
|
|
|
|
|
|
ui_dialogConfig = new DialogConfig;
|
|
|
|
|
|
}
|
|
|
|
|
|
ui_dialogConfig->show();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_btn_flow_clicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 机械臂连接/断开
|
|
|
|
|
|
static bool isConnected = false;
|
|
|
|
|
|
isConnected = !isConnected;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_btn_start_clicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用Presenter启动检测
|
|
|
|
|
|
if (m_presenter) {
|
|
|
|
|
|
m_presenter->StartDetection();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_btn_stop_clicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_presenter) {
|
|
|
|
|
|
m_presenter->StopDetection();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-08 23:51:48 +08:00
|
|
|
|
//void MainWindow::on_menu_camera_triggered()
|
|
|
|
|
|
//{
|
|
|
|
|
|
// qDebug() << __func__ ;
|
|
|
|
|
|
//}
|
2025-06-08 12:48:04 +08:00
|
|
|
|
|
2025-06-08 23:51:48 +08:00
|
|
|
|
//void MainWindow::on_menu_config_triggered()
|
|
|
|
|
|
//{
|
|
|
|
|
|
// qDebug() << __func__ ;
|
|
|
|
|
|
// if(nullptr == ui_dialogConfig){
|
|
|
|
|
|
// ui_dialogConfig = new DialogConfig(this);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ui_dialogConfig->show();
|
|
|
|
|
|
//}
|
2025-06-08 12:48:04 +08:00
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_menu_camera_adjust_triggered()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 状态更新槽函数
|
|
|
|
|
|
void MainWindow::OnStatusUpdate(const std::string& statusMessage)
|
|
|
|
|
|
{
|
|
|
|
|
|
updateStatusLog(QString::fromStdString(statusMessage));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::OnDetectionResult(const DetectionResult& result)
|
|
|
|
|
|
{
|
2025-06-08 23:51:48 +08:00
|
|
|
|
// 通过信号槽机制更新UI(确保在主线程中执行)
|
|
|
|
|
|
emit detectionResultUpdateRequested(result);
|
2025-06-08 12:48:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::OnCamera1StatusChanged(bool isConnected)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 更新相机1状态指示灯
|
|
|
|
|
|
setStatusDot(ui->label_camera_1_status, isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态消息
|
2025-06-08 23:51:48 +08:00
|
|
|
|
QString statusMsg = isConnected ? tr("相机一已连接") : tr("相机一已断开");
|
2025-06-08 12:48:04 +08:00
|
|
|
|
ui->label_camera_1_txt->setText(statusMsg);
|
|
|
|
|
|
updateStatusLog(statusMsg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 相机2状态更新槽函数
|
|
|
|
|
|
void MainWindow::OnCamera2StatusChanged(bool isConnected)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 更新相机2状态指示灯
|
|
|
|
|
|
setStatusDot(ui->label_camera_2_status, isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态消息
|
2025-06-08 23:51:48 +08:00
|
|
|
|
QString statusMsg = isConnected ? tr("相机二已连接") : tr("相机二已断开");
|
2025-06-08 12:48:04 +08:00
|
|
|
|
ui->label_camera_2_txt->setText(statusMsg);
|
|
|
|
|
|
updateStatusLog(statusMsg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 相机个数更新槽函数
|
|
|
|
|
|
void MainWindow::OnCameraCountChanged(int cameraCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 如果只有一个相机,隐藏相机2相关UI元素
|
|
|
|
|
|
if (cameraCount < 2) {
|
|
|
|
|
|
// 隐藏相机2状态标签和图标
|
|
|
|
|
|
ui->label_camera_2_txt->setVisible(false);
|
|
|
|
|
|
ui->label_camera_2_status->setVisible(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态消息
|
|
|
|
|
|
updateStatusLog(tr("系统使用单相机模式"));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 显示相机2状态标签和图标
|
|
|
|
|
|
ui->label_camera_2_txt->setVisible(true);
|
|
|
|
|
|
ui->label_camera_2_status->setVisible(true);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态消息
|
|
|
|
|
|
updateStatusLog(tr("系统使用双相机模式"));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 机械臂状态更新槽函数
|
|
|
|
|
|
void MainWindow::OnRobotConnectionChanged(bool isConnected)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 更新机械臂状态指示灯
|
|
|
|
|
|
setStatusDot(ui->label_robot_status, isConnected);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态消息
|
|
|
|
|
|
QString statusMsg = isConnected ? tr("机械臂已连接") : tr("机械臂已断开");
|
2025-06-08 23:51:48 +08:00
|
|
|
|
updateStatusLog(statusMsg);
|
2025-06-08 12:48:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 工作状态更新槽函数
|
|
|
|
|
|
void MainWindow::OnWorkStatusChanged(WorkStatus status)
|
2025-06-08 23:51:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 通过信号槽机制更新UI(确保在主线程中执行)
|
|
|
|
|
|
emit workStatusUpdateRequested(status);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::updateWorkStatusLabel(WorkStatus status)
|
2025-06-08 12:48:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 获取状态对应的显示文本
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 同时更新状态栏信息
|
|
|
|
|
|
updateStatusLog(statusText);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-08 23:51:48 +08:00
|
|
|
|
void MainWindow::updateDetectionResultDisplay(const DetectionResult& result)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 实现检测结果显示的逻辑
|
|
|
|
|
|
displayImage(result.image);
|
|
|
|
|
|
addDetectionResult(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::on_action_camera_1_triggered()
|
|
|
|
|
|
{
|
|
|
|
|
|
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_action_camera_2_triggered()
|
|
|
|
|
|
{
|
|
|
|
|
|
IVrEyeDevice* pDevice = m_presenter->GetEyeDevice(1);
|
|
|
|
|
|
if(nullptr == pDevice){
|
|
|
|
|
|
QMessageBox::warning(this, "设备错误", "相机设备未正确初始化!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(nullptr == ui_dialogCamera){
|
|
|
|
|
|
ui_dialogCamera = new DialogCamera(pDevice, this);
|
|
|
|
|
|
}
|
|
|
|
|
|
ui_dialogCamera->show();
|
|
|
|
|
|
}
|
2025-06-08 12:48:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|