485 lines
15 KiB
C++
485 lines
15 KiB
C++
#include "mainwindow.h"
|
||
#include "ui_mainwindow.h"
|
||
#include <QMessageBox>
|
||
#include <QDebug>
|
||
#include <QScreen>
|
||
#include <QApplication>
|
||
#include <QLabel>
|
||
#include <QMouseEvent>
|
||
#include <QSizeGrip>
|
||
#include <QSettings>
|
||
#include <QCoreApplication>
|
||
#include <QTimer>
|
||
#include "Version.h"
|
||
#include "StyledMessageBox.h"
|
||
#include "DialogConfig.h"
|
||
|
||
MainWindow::MainWindow(QWidget *parent)
|
||
: QMainWindow(parent)
|
||
, ui(new Ui::MainWindow)
|
||
{
|
||
ui->setupUi(this);
|
||
|
||
// 设置窗口图标
|
||
#ifdef _WIN32
|
||
this->setWindowIcon(QIcon(":/resource/logo.ico"));
|
||
#else
|
||
this->setWindowIcon(QIcon(":/resource/logo.png"));
|
||
#endif
|
||
|
||
// 隐藏标题栏
|
||
setWindowFlags(Qt::FramelessWindowHint);
|
||
|
||
// 设置状态栏
|
||
QFont statusFont = statusBar()->font();
|
||
statusFont.setPointSize(12);
|
||
statusBar()->setFont(statusFont);
|
||
statusBar()->setStyleSheet("QStatusBar { color: rgb(239, 241, 245); padding: 20px; }");
|
||
|
||
// 添加版本信息到状态栏(只显示版本号)
|
||
QString versionText = QString("%1").arg(GetControlVersionOnly());
|
||
QLabel* versionLabel = new QLabel(versionText);
|
||
versionLabel->setStyleSheet("color: rgb(239, 241, 245); font-size: 20px;");
|
||
statusBar()->addPermanentWidget(versionLabel);
|
||
|
||
|
||
// 设置窗口大小为1200x700,不自动最大化
|
||
this->resize(1200, 700);
|
||
this->setMinimumSize(1200, 700); // 设置最小尺寸
|
||
|
||
// 安装事件过滤器到顶部groupBox,用于拖动窗口
|
||
ui->groupBox->installEventFilter(this);
|
||
|
||
// 初始化工作流程显示组件
|
||
m_workflowWidget = new WorkflowWidget(this);
|
||
QVBoxLayout* workflowLayout = new QVBoxLayout(ui->frame_workflow);
|
||
workflowLayout->setContentsMargins(0, 0, 0, 0);
|
||
workflowLayout->addWidget(m_workflowWidget);
|
||
|
||
// 初始化设备状态显示组件
|
||
m_deviceStatusWidget = new DeviceStatusWidget(this);
|
||
m_deviceStatusWidget->setCameraCount(1); // 显示1个相机(用于显示控制器状态)
|
||
m_deviceStatusWidget->setCamera1Name("控制器");
|
||
m_deviceStatusWidget->setCameraClickable(false); // 控制器不可点击
|
||
QVBoxLayout* deviceLayout = new QVBoxLayout(ui->frame_device);
|
||
deviceLayout->setContentsMargins(0, 0, 0, 0);
|
||
deviceLayout->addWidget(m_deviceStatusWidget);
|
||
|
||
// 初始化日志辅助类
|
||
m_logHelper = new DetectLogHelper(ui->detect_log, this);
|
||
|
||
// 创建Presenter
|
||
m_presenter = new DemoControlPresenter(this);
|
||
|
||
// 连接信号槽
|
||
connect(m_presenter, &DemoControlPresenter::statusMessageUpdated,
|
||
this, &MainWindow::onStatusMessageUpdated);
|
||
connect(m_presenter, &DemoControlPresenter::workflowStepChanged,
|
||
this, &MainWindow::onWorkflowStepChanged);
|
||
connect(m_presenter, &DemoControlPresenter::controllerConnectionChanged,
|
||
this, &MainWindow::onControllerConnectionChanged);
|
||
connect(m_presenter, &DemoControlPresenter::robotConnectionChanged,
|
||
this, &MainWindow::onRobotConnectionChanged);
|
||
connect(m_presenter, &DemoControlPresenter::detectionResultUpdated,
|
||
this, &MainWindow::onDetectionResultUpdated);
|
||
|
||
// 初始化按钮状态
|
||
ui->btn_pause->setEnabled(false);
|
||
ui->btn_step->setEnabled(true);
|
||
|
||
// 初始化
|
||
Init();
|
||
}
|
||
|
||
MainWindow::~MainWindow()
|
||
{
|
||
if (m_presenter) {
|
||
delete m_presenter;
|
||
m_presenter = nullptr;
|
||
}
|
||
delete ui;
|
||
}
|
||
|
||
void MainWindow::Init()
|
||
{
|
||
updateStatusLog("主控程序初始化中...");
|
||
|
||
// 在线程中执行初始化
|
||
std::thread initThread([this]() {
|
||
int result = m_presenter->Init();
|
||
if (result != 0) {
|
||
updateStatusLog(QString("初始化失败,错误码:%1").arg(result));
|
||
} else {
|
||
updateStatusLog("系统初始化完成");
|
||
}
|
||
|
||
// 从配置文件加载配置
|
||
QMetaObject::invokeMethod(this, [this]() {
|
||
// 加载配置到Presenter
|
||
DialogConfig::LoadConfigToPresenter(m_presenter);
|
||
updateStatusLog("配置已加载");
|
||
|
||
// 从配置文件读取连接参数
|
||
QSettings settings(DialogConfig::GetConfigFilePath(), QSettings::IniFormat);
|
||
QString controllerIP = settings.value("Controller/IP", "192.168.0.88").toString();
|
||
int controllerPort = settings.value("Controller/Port", 502).toInt();
|
||
QString robotIP = settings.value("Robot/IP", "192.168.58.2").toString();
|
||
|
||
updateStatusLog(QString("正在连接控制器 %1:%2...").arg(controllerIP).arg(controllerPort));
|
||
m_presenter->ConnectToController(controllerIP, controllerPort);
|
||
|
||
updateStatusLog(QString("正在连接机械臂 %1...").arg(robotIP));
|
||
m_presenter->ConnectToRobot(robotIP);
|
||
}, Qt::QueuedConnection);
|
||
});
|
||
|
||
initThread.detach();
|
||
}
|
||
|
||
void MainWindow::updateStatusLog(const QString& message)
|
||
{
|
||
if (m_logHelper) {
|
||
m_logHelper->appendLog(message);
|
||
}
|
||
}
|
||
|
||
void MainWindow::on_btn_start_clicked()
|
||
{
|
||
if (!m_presenter) {
|
||
updateStatusLog("系统未初始化");
|
||
return;
|
||
}
|
||
|
||
if (!m_presenter->IsControllerConnected()) {
|
||
StyledMessageBox::warning(this, "警告", "控制器未连接,无法启动工作流程");
|
||
return;
|
||
}
|
||
|
||
if (!m_presenter->IsRobotConnected()) {
|
||
StyledMessageBox::warning(this, "警告", "机械臂未连接,无法启动工作流程");
|
||
return;
|
||
}
|
||
|
||
updateStatusLog("启动工作流程...");
|
||
m_presenter->StartWorkflow();
|
||
|
||
// 更新按钮状态:连续执行模式
|
||
ui->btn_start->setEnabled(false);
|
||
ui->btn_pause->setEnabled(true);
|
||
ui->btn_pause->setText("暂停");
|
||
ui->btn_step->setEnabled(false); // 连续执行时禁用单步
|
||
}
|
||
|
||
void MainWindow::on_btn_stop_clicked()
|
||
{
|
||
if (!m_presenter) {
|
||
updateStatusLog("系统未初始化");
|
||
return;
|
||
}
|
||
|
||
updateStatusLog("停止工作流程...");
|
||
m_presenter->StopWorkflow();
|
||
m_workflowWidget->reset();
|
||
|
||
// 更新按钮状态:停止后恢复初始状态
|
||
ui->btn_start->setEnabled(true);
|
||
ui->btn_pause->setEnabled(false);
|
||
ui->btn_pause->setText("暂停");
|
||
ui->btn_step->setEnabled(true);
|
||
}
|
||
|
||
void MainWindow::on_btn_pause_clicked()
|
||
{
|
||
if (!m_presenter) {
|
||
updateStatusLog("系统未初始化");
|
||
return;
|
||
}
|
||
|
||
if (m_presenter->IsWorkflowPaused()) {
|
||
// 当前是暂停状态,点击恢复
|
||
updateStatusLog("恢复工作流程...");
|
||
m_presenter->ResumeWorkflow();
|
||
ui->btn_pause->setText("暂停");
|
||
ui->btn_step->setEnabled(false); // 恢复后禁用单步
|
||
ui->btn_start->setEnabled(false); // 恢复后禁用开始
|
||
} else {
|
||
// 当前是运行状态,点击暂停
|
||
updateStatusLog("暂停工作流程...");
|
||
m_presenter->PauseWorkflow();
|
||
ui->btn_pause->setText("继续");
|
||
ui->btn_step->setEnabled(true); // 暂停后启用单步
|
||
ui->btn_start->setEnabled(false); // 暂停时仍然禁用开始
|
||
}
|
||
}
|
||
|
||
void MainWindow::on_btn_step_clicked()
|
||
{
|
||
if (!m_presenter) {
|
||
updateStatusLog("系统未初始化");
|
||
return;
|
||
}
|
||
|
||
if (!m_presenter->IsControllerConnected()) {
|
||
StyledMessageBox::warning(this, "警告", "控制器未连接,无法执行单步");
|
||
return;
|
||
}
|
||
|
||
if (!m_presenter->IsRobotConnected()) {
|
||
StyledMessageBox::warning(this, "警告", "机械臂未连接,无法执行单步");
|
||
return;
|
||
}
|
||
|
||
updateStatusLog("执行单步...");
|
||
m_presenter->StepWorkflow();
|
||
|
||
// 更新按钮状态
|
||
if (!m_presenter->IsWorkflowRunning()) {
|
||
// 首次单步,启动工作流程
|
||
ui->btn_start->setEnabled(false);
|
||
ui->btn_pause->setEnabled(true);
|
||
ui->btn_pause->setText("继续");
|
||
}
|
||
}
|
||
|
||
void MainWindow::on_btn_config_clicked()
|
||
{
|
||
if (!m_presenter) {
|
||
updateStatusLog("系统未初始化");
|
||
return;
|
||
}
|
||
|
||
if (!m_dialogConfig) {
|
||
m_dialogConfig = new DialogConfig(m_presenter, this);
|
||
}
|
||
|
||
m_dialogConfig->exec();
|
||
}
|
||
|
||
void MainWindow::on_btn_fullscreen_clicked()
|
||
{
|
||
if (m_isFullScreen) {
|
||
// 退出全屏,恢复到正常窗口
|
||
setWindowFlags(Qt::FramelessWindowHint);
|
||
setGeometry(m_normalGeometry);
|
||
showNormal();
|
||
m_isFullScreen = false;
|
||
updateStatusLog("退出全屏");
|
||
} else {
|
||
// 进入全屏
|
||
m_normalGeometry = geometry();
|
||
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
||
showFullScreen();
|
||
m_isFullScreen = true;
|
||
updateStatusLog("进入全屏");
|
||
}
|
||
}
|
||
|
||
void MainWindow::on_btn_hide_clicked()
|
||
{
|
||
this->showMinimized();
|
||
}
|
||
|
||
void MainWindow::on_btn_close_clicked()
|
||
{
|
||
this->close();
|
||
}
|
||
|
||
void MainWindow::onStatusMessageUpdated(const QString& message)
|
||
{
|
||
updateStatusLog(message);
|
||
}
|
||
|
||
void MainWindow::onWorkflowStepChanged(WorkflowStep step, const QString& message)
|
||
{
|
||
m_workflowWidget->updateStep(step);
|
||
updateStatusLog(message);
|
||
|
||
// 如果工作流程完成,检查是否真的结束了
|
||
if (step == WorkflowStep::Completed) {
|
||
// 延迟检查工作流程是否真的停止
|
||
QTimer::singleShot(100, this, [this]() {
|
||
if (!m_presenter->IsWorkflowRunning()) {
|
||
// 工作流程已停止,更新按钮状态
|
||
ui->btn_start->setEnabled(true);
|
||
ui->btn_pause->setEnabled(false);
|
||
ui->btn_pause->setText("暂停");
|
||
ui->btn_step->setEnabled(true);
|
||
} else if (m_presenter->IsWorkflowStepMode()) {
|
||
// 单步模式下完成一轮,保持"继续"按钮状态不变
|
||
// 按钮应该显示"继续",因为处于单步等待状态
|
||
ui->btn_pause->setText("继续");
|
||
}
|
||
});
|
||
} else if (step == WorkflowStep::Error) {
|
||
// 出错时立即更新按钮状态
|
||
ui->btn_start->setEnabled(true);
|
||
ui->btn_pause->setEnabled(false);
|
||
ui->btn_pause->setText("暂停");
|
||
ui->btn_step->setEnabled(true);
|
||
}
|
||
}
|
||
|
||
void MainWindow::onControllerConnectionChanged(bool connected)
|
||
{
|
||
// 更新设备状态显示(使用相机1状态显示控制器连接状态)
|
||
if (m_deviceStatusWidget) {
|
||
m_deviceStatusWidget->updateCamera1Status(connected);
|
||
}
|
||
|
||
if (connected) {
|
||
updateStatusLog("控制器已连接");
|
||
} else {
|
||
updateStatusLog("控制器已断开");
|
||
}
|
||
}
|
||
|
||
void MainWindow::onRobotConnectionChanged(bool connected)
|
||
{
|
||
if (m_deviceStatusWidget) {
|
||
m_deviceStatusWidget->updateRobotStatus(connected);
|
||
}
|
||
|
||
if (connected) {
|
||
updateStatusLog("机械臂已连接");
|
||
} else {
|
||
updateStatusLog("机械臂已断开");
|
||
}
|
||
}
|
||
|
||
void MainWindow::onDetectionResultUpdated(const DetectionResult& result)
|
||
{
|
||
m_workflowWidget->updateDetectionResult(result);
|
||
}
|
||
|
||
void MainWindow::mousePressEvent(QMouseEvent *event)
|
||
{
|
||
if (event->button() == Qt::LeftButton) {
|
||
ResizeRegion region = getResizeRegion(event->pos());
|
||
if (region != None) {
|
||
// 开始缩放
|
||
m_isResizing = true;
|
||
m_resizeRegion = region;
|
||
m_resizeStartPos = event->globalPos();
|
||
m_resizeStartGeometry = this->geometry();
|
||
event->accept();
|
||
}
|
||
}
|
||
}
|
||
|
||
void MainWindow::mouseMoveEvent(QMouseEvent *event)
|
||
{
|
||
if (m_isResizing && (event->buttons() & Qt::LeftButton)) {
|
||
// 处理窗口缩放
|
||
QPoint delta = event->globalPos() - m_resizeStartPos;
|
||
QRect newGeometry = m_resizeStartGeometry;
|
||
|
||
if (m_resizeRegion & Left) {
|
||
newGeometry.setLeft(m_resizeStartGeometry.left() + delta.x());
|
||
}
|
||
if (m_resizeRegion & Right) {
|
||
newGeometry.setRight(m_resizeStartGeometry.right() + delta.x());
|
||
}
|
||
if (m_resizeRegion & Top) {
|
||
newGeometry.setTop(m_resizeStartGeometry.top() + delta.y());
|
||
}
|
||
if (m_resizeRegion & Bottom) {
|
||
newGeometry.setBottom(m_resizeStartGeometry.bottom() + delta.y());
|
||
}
|
||
|
||
// 确保不小于最小尺寸
|
||
if (newGeometry.width() >= minimumWidth() && newGeometry.height() >= minimumHeight()) {
|
||
this->setGeometry(newGeometry);
|
||
}
|
||
event->accept();
|
||
} else if (!m_isDragging) {
|
||
// 更新鼠标光标
|
||
ResizeRegion region = getResizeRegion(event->pos());
|
||
updateCursor(region);
|
||
}
|
||
}
|
||
|
||
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
|
||
{
|
||
if (event->button() == Qt::LeftButton) {
|
||
m_isResizing = false;
|
||
m_resizeRegion = None;
|
||
m_isDragging = false;
|
||
updateCursor(None);
|
||
event->accept();
|
||
}
|
||
}
|
||
|
||
MainWindow::ResizeRegion MainWindow::getResizeRegion(const QPoint& pos)
|
||
{
|
||
int region = None;
|
||
|
||
if (pos.x() <= RESIZE_BORDER_WIDTH) {
|
||
region |= Left;
|
||
} else if (pos.x() >= width() - RESIZE_BORDER_WIDTH) {
|
||
region |= Right;
|
||
}
|
||
|
||
if (pos.y() <= RESIZE_BORDER_WIDTH) {
|
||
region |= Top;
|
||
} else if (pos.y() >= height() - RESIZE_BORDER_WIDTH) {
|
||
region |= Bottom;
|
||
}
|
||
|
||
return static_cast<ResizeRegion>(region);
|
||
}
|
||
|
||
void MainWindow::updateCursor(ResizeRegion region)
|
||
{
|
||
switch (region) {
|
||
case TopLeft:
|
||
case BottomRight:
|
||
setCursor(Qt::SizeFDiagCursor);
|
||
break;
|
||
case TopRight:
|
||
case BottomLeft:
|
||
setCursor(Qt::SizeBDiagCursor);
|
||
break;
|
||
case Left:
|
||
case Right:
|
||
setCursor(Qt::SizeHorCursor);
|
||
break;
|
||
case Top:
|
||
case Bottom:
|
||
setCursor(Qt::SizeVerCursor);
|
||
break;
|
||
default:
|
||
setCursor(Qt::ArrowCursor);
|
||
break;
|
||
}
|
||
}
|
||
|
||
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||
{
|
||
// 只在顶部groupBox区域允许拖动
|
||
if (obj == ui->groupBox) {
|
||
if (event->type() == QEvent::MouseButtonPress) {
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||
if (mouseEvent->button() == Qt::LeftButton) {
|
||
m_isDragging = true;
|
||
m_dragPosition = mouseEvent->globalPos() - this->frameGeometry().topLeft();
|
||
return true;
|
||
}
|
||
}
|
||
else if (event->type() == QEvent::MouseMove) {
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||
if (m_isDragging && (mouseEvent->buttons() & Qt::LeftButton)) {
|
||
this->move(mouseEvent->globalPos() - m_dragPosition);
|
||
return true;
|
||
}
|
||
}
|
||
else if (event->type() == QEvent::MouseButtonRelease) {
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||
if (mouseEvent->button() == Qt::LeftButton) {
|
||
m_isDragging = false;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return QMainWindow::eventFilter(obj, event);
|
||
}
|