diff --git a/HPPA/CaptureCoordinator.cpp b/HPPA/CaptureCoordinator.cpp index 596d5f9..902095f 100644 --- a/HPPA/CaptureCoordinator.cpp +++ b/HPPA/CaptureCoordinator.cpp @@ -97,7 +97,6 @@ void TwoMotionCaptureCoordinator::stop() std::cout << "The user manually stops the collection! " << std::endl; savePathLinesToCsv(); - emit sequenceComplete(1); emit finishRecordLineNumSignal(m_numCurrentPathLine); //emit stopRecordHSISignal(m_numCurrentPathLine); if (m_cameraCtrl != nullptr) @@ -106,6 +105,8 @@ void TwoMotionCaptureCoordinator::stop() } move2LocBeforeStart(); + + emit sequenceComplete(1); } void TwoMotionCaptureCoordinator::getLocBeforeStart() @@ -471,7 +472,8 @@ OneMotionCaptureCoordinator::OneMotionCaptureCoordinator( OneMotionCaptureCoordinator::~OneMotionCaptureCoordinator() { - + disconnect(m_motorCtrl, &IrisMultiMotorController::motorStopSignal, + this, &OneMotionCaptureCoordinator::handleMotorStoped); } void OneMotionCaptureCoordinator::startStepMotion(OneMotionCapturePathLine pathLine) @@ -585,6 +587,10 @@ void OneMotionCaptureCoordinator::handleMotorStoped(int motorID, double pos) m_cameraCtrl->stop_record(); } move2LocBeforeStart(); + + // emit sequenceComplete last: the slot connected to it may delete this object, + // so no member access is allowed after this point. + emit sequenceComplete(0); } void OneMotionCaptureCoordinator::handleCaptureComplete(double index) diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index 08feac2..d6a7925 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -506,6 +506,10 @@ HPPA::HPPA(QWidget* parent) //光谱仪操作 m_Imager = nullptr; + m_RecordThread = nullptr; + m_CopyFileThread = nullptr; + m_FileOperation = nullptr; + m_TestImagerStausThread = nullptr; m_RecordState = 0; connect(this->ui.action_connect_imager, SIGNAL(triggered()), this, SLOT(onconnect()));//信号与槽:连接相机,相机操作相关信号与槽绑定放在函数onconnect中 @@ -799,6 +803,13 @@ void HPPA::initControlTabwidget() void HPPA::recordFromRobotArm(int fileCounter) { + if (!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + + return; + } + //qDebug() << "recordFromRobotArm" << fileCounter; if (fileCounter == -1) @@ -957,11 +968,7 @@ HPPA::~HPPA() file.close(); } - if (m_Imager != nullptr) - { - //m_Imager->~ResononNirImager();//释放资源 - delete m_Imager; - } + disconnectImagerAndCleanup(); if (s_instance == this) { @@ -1253,14 +1260,156 @@ void HPPA::createPlantPhenotypeScenario() } +bool HPPA::testImagerVality() +{ + try + { + if (m_Imager == nullptr) + { + return false; + } + double framerate = m_Imager->getFramerate(); + m_Imager->setFramerate(framerate); + + return true; + } + catch (const std::exception& e) + { + disconnectImagerAndCleanup(); + return false; + } + catch (int e)//ximea相机异常 + { + disconnectImagerAndCleanup(); + return false; + } + catch (...) + { + disconnectImagerAndCleanup(); + return false; + } +} + +void HPPA::showMessageBox(QString msg, QString title) +{ + QMessageBox msgBox(this); + msgBox.setWindowTitle(title); + msgBox.setText(msg); + msgBox.setStyleSheet(R"( + QMessageBox { + background-color: #0D1233; + } + QMessageBox QLabel { + color: #ACCDFF; + font-size: 14px; + } + QPushButton { + background-color: #142D7F; + color: #e6eeff; + border: 1px solid #2f6bff; + border-radius: 6px; + padding: 6px 20px; + min-width: 60px; + font-size: 13px; + } + QPushButton:hover { + border: 1px solid #4d8dff; + background-color: red; + } + QPushButton:pressed { + background-color: #23345c; + } + )"); + + msgBox.exec(); +} + +bool HPPA::showResultMessageBox(QString title, QString msg) +{ + QMessageBox msgBox(this); + msgBox.setWindowTitle(title); + msgBox.setText(msg); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + msgBox.setStyleSheet(R"( + QMessageBox { + background-color: #0D1233; + } + QMessageBox QLabel { + color: #ACCDFF; + font-size: 14px; + } + QPushButton { + background-color: #142D7F; + color: #e6eeff; + border: 1px solid #2f6bff; + border-radius: 6px; + padding: 6px 20px; + min-width: 60px; + font-size: 13px; + } + QPushButton:hover { + border: 1px solid #4d8dff; + background-color: red; + } + QPushButton:pressed { + background-color: #23345c; + } + )"); + + QMessageBox::StandardButton ret = static_cast(msgBox.exec()); + + if (ret == QMessageBox::Yes) + { + return true; + } + else + { + return false; + } +} + void HPPA::onStartRecordStep1() { + //判断移动平台 QAction* checked = moveplatformActionGroup->checkedAction(); if (!checked) { - QMessageBox msgBox; - msgBox.setText(QString::fromLocal8Bit("请选择扫描平台!")); - msgBox.exec(); + showMessageBox(QString::fromLocal8Bit("请选择扫描平台!")); + return; + } + + QString checkedName = checked->objectName(); + if (checkedName == "mAction_is_no_motor") + { + + } + else if (checkedName == "mAction_1AxisMotor") + { + if (!m_omc->getMotorsConnectionStatus()) + { + showMessageBox(QString::fromLocal8Bit("找不到马达!")); + return; + } + } + else if (checkedName == "mAction_2AxisMotor_new") + { + if (!m_tmc->getMotorsConnectionStatus()) + { + showMessageBox(QString::fromLocal8Bit("找不到马达!")); + return; + } + } + else if (checkedName == "mAction_RobotArm") + { + + } + + //判断光谱仪 + if(!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + return; } @@ -1277,14 +1426,9 @@ void HPPA::onStartRecordStep1() int x = _access(tmp.c_str(), 0); if (!x)//如果文件存在就执行此if的代码 { - enum QMessageBox::StandardButton response = QMessageBox::question(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("文件存在!是否覆盖?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);; - if (response == QMessageBox::Yes)// + bool res = showResultMessageBox(QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("文件存在!是否覆盖?")); + if (!res) { - //std::cout << "覆盖" << std::endl; - } - else - { - //std::cout << "不覆盖" << std::endl; return; } } @@ -1294,7 +1438,7 @@ void HPPA::onStartRecordStep1() m_RecordState -= 1; } - QString checkedName = checked->objectName(); + if (checkedName == "mAction_is_no_motor") { m_RecordState += 1; @@ -1317,7 +1461,7 @@ void HPPA::onStartRecordStep1() m_RecordState -= 1; ui.action_start_recording->setText(QString::fromLocal8Bit("采集")); - ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_done.svg")); + ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_done.svg")); //ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}"); } return; @@ -1332,7 +1476,7 @@ void HPPA::onStartRecordStep1() removeAllLayersInRasterGroup(); ui.action_start_recording->setText(QString::fromLocal8Bit("停止采集")); - ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_ing.svg")); + ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_ing.svg")); //ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(255,0,0);}"); //应该先控制马达运动,当马达运动后,再开始光谱仪采集(发射开始采集信号) @@ -1360,14 +1504,14 @@ void HPPA::onStartRecordStep1() //m_imageViewerTabWidget->clear(); removeAllLayersInRasterGroup(); + ui.action_start_recording->setText(QString::fromLocal8Bit("停止采集")); + ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_ing.svg")); + //ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(255,0,0);}"); + emit updateRecordingFileInfoSignal(AppSettings::instance().dataFolder(), AppSettings::instance().fileName(), this->frame_number->text().toInt()); m_tmc->setImager(m_Imager); m_tmc->setPosFileName(QString::fromStdString(x_location)); m_tmc->run(); - - ui.action_start_recording->setText(QString::fromLocal8Bit("停止采集")); - ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record_ing.svg")); - //ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(255,0,0);}"); } else { @@ -1489,18 +1633,21 @@ void HPPA::onActionOpenDirectory() void HPPA::onFramerateChanged(double framerate) { + if (!m_Imager) return; m_Imager->setFramerate(framerate); m_hic->setFrameRate(m_Imager->getFramerate()); } void HPPA::onIntegrationTimeChanged(double integrationTime) { + if (!m_Imager) return; m_Imager->setIntegrationTime(integrationTime); m_hic->setIntegrationTime(m_Imager->getIntegrationTime()); } void HPPA::onGainChanged(double gain) { + if (!m_Imager) return; m_Imager->setGain(gain); m_hic->setGain(m_Imager->getGain()); } @@ -1670,40 +1817,8 @@ void HPPA::onExit() void HPPA::closeEvent(QCloseEvent* event) { - QMessageBox msgBox(this); - msgBox.setWindowTitle(QString::fromLocal8Bit("退出确认")); - msgBox.setText(QString::fromLocal8Bit("确定要退出程序吗?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - msgBox.setStyleSheet(R"( - QMessageBox { - background-color: #0D1233; - } - QMessageBox QLabel { - color: #ACCDFF; - font-size: 14px; - } - QPushButton { - background-color: #142D7F; - color: #e6eeff; - border: 1px solid #2f6bff; - border-radius: 6px; - padding: 6px 20px; - min-width: 60px; - font-size: 13px; - } - QPushButton:hover { - border: 1px solid #4d8dff; - background-color: red; - } - QPushButton:pressed { - background-color: #23345c; - } - )"); - - QMessageBox::StandardButton ret = static_cast(msgBox.exec()); - - if (ret == QMessageBox::Yes) + bool res = showResultMessageBox(QString::fromLocal8Bit("退出确认"), QString::fromLocal8Bit("确定要退出程序吗?")); + if (res) { event->accept(); // 允许关闭 } @@ -1733,12 +1848,104 @@ void HPPA::onOpenImg() addLayer(baseName, uri, true); } +void HPPA::disconnectImagerAndCleanup() +{ + if (m_Imager == nullptr) + return; + + // 如果正在采集,先停止 + if (m_RecordState % 2 == 1) + { + m_Imager->setRecordControlState(false); + m_RecordState = 0; + } + + // 断开所有与 m_Imager 相关的信号槽 + disconnect(m_Imager, nullptr, this, nullptr); + disconnect(this, SIGNAL(StartFocusSignal()), m_Imager, SLOT(focus())); + disconnect(this, SIGNAL(StartRecordSignal()), m_Imager, SLOT(start_record())); + disconnect(this, &HPPA::updateRecordingFileInfoSignal, m_Imager, &ImagerOperationBase::updateRecordingFileInfo); + disconnect(this, SIGNAL(RecordWhiteSignal()), m_Imager, SLOT(record_white())); + disconnect(this, SIGNAL(RecordDarlSignal()), m_Imager, SLOT(record_dark())); + + // 断开 UI 控件与本类槽的连接(它们在 onconnect 中绑定,避免重复连接) + disconnect(ui.action_auto_exposure, SIGNAL(triggered()), this, SLOT(onAutoExposure())); + disconnect(ui.action_focus, SIGNAL(triggered()), this, SLOT(onFocus1())); + disconnect(ui.action_dark, SIGNAL(triggered()), this, SLOT(onDark())); + disconnect(ui.action_reference, SIGNAL(triggered()), this, SLOT(onReference())); + disconnect(ui.action_start_recording, SIGNAL(triggered()), this, SLOT(onStartRecordStep1())); + disconnect(ui.actionOpenDirectory, SIGNAL(triggered()), this, SLOT(onActionOpenDirectory())); + disconnect(m_hic, SIGNAL(framerateChanged(double)), this, SLOT(onFramerateChanged(double))); + disconnect(m_hic, SIGNAL(integrationTimeChanged(double)), this, SLOT(onIntegrationTimeChanged(double))); + disconnect(m_hic, SIGNAL(gainChanged(double)), this, SLOT(onGainChanged(double))); + + // 停止采集线程 + if (m_RecordThread) + { + m_RecordThread->quit(); + m_RecordThread->wait(3000); + delete m_RecordThread; + m_RecordThread = nullptr; + } + + // 停止文件拷贝线程 + if (m_CopyFileThread) + { + if (m_FileOperation) + { + disconnect(this, SIGNAL(CopyFileThreadSignal(QString, QString)), m_FileOperation, SLOT(copyFile(QString, QString))); + disconnect(m_FileOperation, SIGNAL(CopyFinishedSignal()), this, SLOT(onCopyFinished())); + } + m_CopyFileThread->quit(); + m_CopyFileThread->wait(3000); + delete m_FileOperation; + m_FileOperation = nullptr; + delete m_CopyFileThread; + m_CopyFileThread = nullptr; + } + + // 删除 imager 对象 + try + { + m_Imager->disconnectImager(); + } + catch (...) + { + // 断连时忽略异常 + } + delete m_Imager; + m_Imager = nullptr; + + // 禁用相机参数控件 + frame_number->setEnabled(false); + m_hic->setDisabled(true); + + // 重置图标 + ui.action_connect_imager->setIcon(QIcon(":/svg/resources/icons/svg/connect_imager.svg")); + ui.action_auto_exposure->setIcon(QIcon(":/svg/resources/icons/svg/exposure.svg")); + ui.action_dark->setIcon(QIcon(":/svg/resources/icons/svg/dark.svg")); + ui.action_reference->setIcon(QIcon(":/svg/resources/icons/svg/reference.svg")); + ui.action_start_recording->setIcon(QIcon(":/svg/resources/icons/svg/record.svg")); + ui.action_start_recording->setText(QString::fromLocal8Bit("采集")); +} + void HPPA::onconnect() { - if (m_Imager != nullptr) + if (!testImagerVality()) { - //std::cout << "相机已经连接!" << std::endl; - return; + disconnectImagerAndCleanup(); + } + else + { + bool res = showResultMessageBox(QString::fromLocal8Bit("相机连接"), QString::fromLocal8Bit("确定要重连相机吗?")); + if (res) + { + disconnectImagerAndCleanup(); + } + else + { + return; + } } try @@ -1766,11 +1973,9 @@ void HPPA::onconnect() } else { - QMessageBox msgBox; - msgBox.setText(QString::fromLocal8Bit("请选择相机!")); - msgBox.exec(); + showMessageBox(QString::fromLocal8Bit("请选择相机类型!")); - return; + return; } ui.action_connect_imager->setIcon(QIcon(":/svg/resources/icons/svg/connect_imager_ing.svg")); @@ -1782,7 +1987,7 @@ void HPPA::onconnect() connect(m_Imager, SIGNAL(PlotSignal(int, int, QString)), this, SLOT(onPlotHyperspectralImageRgbImage(int, int, QString))); connect(m_Imager, SIGNAL(RecordFinishedSignal_WhenFrameNumberMeet()), this, SLOT(onRecordFinishedSignal_WhenFrameNumberMeet())); connect(m_Imager, SIGNAL(RecordFinishedSignal_WhenFrameNumberNotMeet()), this, SLOT(onRecordFinishedSignal_WhenFrameNumberNotMeet())); - connect(m_Imager, SIGNAL(SpectralSignal(int)), this, SLOT(PlotSpectral(int))); + connect(m_Imager, SIGNAL(SpectralSignal(int)), this, SLOT(focusPlotSpectralImg(int))); connect(m_Imager, SIGNAL(testImagerStatus()), this, SLOT(testImagerStatus())); connect(m_Imager, &ImagerOperationBase::autoExposureSignal, this, &HPPA::autoExposureFinished); @@ -1849,13 +2054,17 @@ void HPPA::onconnect() delete m_Imager; m_Imager = nullptr; - QMessageBox msgBox; - msgBox.setText(QString::fromLocal8Bit("请连接相机!")); - msgBox.exec(); + showMessageBox(QString::fromLocal8Bit("请连接相机!")); } + catch (int e)//ximea相机异常 + { + ui.action_connect_imager->setIcon(QIcon(":/svg/resources/icons/svg/connect_imager.svg")); + delete m_Imager; + m_Imager = nullptr; - + showMessageBox(QString::fromLocal8Bit("请连接相机!")); + } } void HPPA::testImagerStatus() @@ -1871,6 +2080,13 @@ void HPPA::autoExposureFinished() void HPPA::onAutoExposure() { + if (!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + + return; + } + ui.action_auto_exposure->setIcon(QIcon(":/svg/resources/icons/svg/exposure_ing.svg")); double ReturnedExposureTime = m_Imager->auto_exposure(); @@ -1883,6 +2099,13 @@ void HPPA::onAutoExposure() void HPPA::onFocus1() { + if (!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + + return; + } + focusWindow* w = new focusWindow(this, m_Imager); connect(w, SIGNAL(StartManualFocusSignal(int)), this, SLOT(onFocus2(int))); connect(w, SIGNAL(closeSignal()), this, SLOT(onFocusWindowClosed())); @@ -1922,14 +2145,16 @@ void HPPA::onFocus2(int command) } else if (command == 0) { - m_Imager->setFocusControlState(false); + if (m_Imager) + m_Imager->setFocusControlState(false); } } void HPPA::onFocusWindowClosed() { //关闭调焦窗口时,停止调焦功能 - m_Imager->setFocusControlState(false); + if (m_Imager) + m_Imager->setFocusControlState(false); //关闭调焦窗口tab int index = m_imageViewerTabWidget->indexOf(m_focusTab); if (index != -1) @@ -1955,9 +2180,14 @@ void HPPA::settingWindow() void HPPA::onDark() { - QMessageBox msgBox; - msgBox.setText(QString::fromLocal8Bit("采集暗电流,请确保镜头盖盖上!")); - msgBox.exec(); + if (!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + + return; + } + + showMessageBox(QString::fromLocal8Bit("采集暗电流,请确保镜头盖盖上!")); ui.action_dark->setIcon(QIcon(":/svg/resources/icons/svg/dark_ing.svg")); @@ -1988,9 +2218,14 @@ void HPPA::recordDarkFinish() void HPPA::onReference() { - QMessageBox msgBox; - msgBox.setText(QString::fromLocal8Bit("请确保白板放置正确!")); - msgBox.exec(); + if (!testImagerVality()) + { + showMessageBox(QString::fromLocal8Bit("找不到光谱仪!")); + + return; + } + + showMessageBox(QString::fromLocal8Bit("请确保白板放置正确!")); ui.action_reference->setIcon(QIcon(":/svg/resources/icons/svg/reference_ing.svg")); @@ -2021,6 +2256,8 @@ void HPPA::recordWhiteFinish() void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath) { + if (!m_Imager) return; + //使用机械臂采集时,会在停止采集后的瞬间又开始采集,会导致上次采集最后发射的信号调用此槽函数报错 QAction* checked = moveplatformActionGroup->checkedAction(); QString checkedName = checked->objectName(); @@ -2068,8 +2305,10 @@ void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QSt //currentImageViewer[0]->SetImage(&QPixmap::fromImage(CuttedImage));//绘制图像 } -void HPPA::PlotSpectral(int state) +void HPPA::focusPlotSpectralImg(int state) { + if (!m_Imager) return; + if (state == 1) { //显示影像 diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 2cbff10..0ec6b92 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -299,10 +299,15 @@ private: QWidget* m_focusTab=nullptr; recordFrameCounter* m_recordFrameCounter = nullptr; - + + bool testImagerVality(); + void showMessageBox(QString msg, QString title= QString::fromLocal8Bit("提示")); + bool showResultMessageBox(QString title, QString msg); + void disconnectImagerAndCleanup(); + public Q_SLOTS: void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath); - void PlotSpectral(int state); + void focusPlotSpectralImg(int state); void onRecordFinishedSignal_WhenFrameNumberMeet(); void onRecordFinishedSignal_WhenFrameNumberNotMeet(); void onsequenceComplete(); diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index db3e56d..ec57941 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -134,6 +134,7 @@ + @@ -227,6 +228,7 @@ + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index 719142f..06f7cd5 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -208,6 +208,9 @@ Source Files + + Source Files + @@ -383,6 +386,9 @@ Header Files + + Header Files + diff --git a/HPPA/MotorWindowBase.cpp b/HPPA/MotorWindowBase.cpp new file mode 100644 index 0000000..e222c2d --- /dev/null +++ b/HPPA/MotorWindowBase.cpp @@ -0,0 +1,11 @@ +#include "MotorWindowBase.h" + +MotorWindowBase::MotorWindowBase() +{ + +} + +MotorWindowBase::~MotorWindowBase() +{ + +} diff --git a/HPPA/MotorWindowBase.h b/HPPA/MotorWindowBase.h new file mode 100644 index 0000000..4de6d15 --- /dev/null +++ b/HPPA/MotorWindowBase.h @@ -0,0 +1,15 @@ +#pragma once + +class MotorWindowBase +{ + +public: + MotorWindowBase(); + ~MotorWindowBase(); + +protected: + virtual bool getMotorsConnectionStatus()=0; + +private: + +}; diff --git a/HPPA/OneMotorControl.cpp b/HPPA/OneMotorControl.cpp index b01f118..ffdbf55 100644 --- a/HPPA/OneMotorControl.cpp +++ b/HPPA/OneMotorControl.cpp @@ -6,6 +6,16 @@ OneMotorControl::OneMotorControl(QWidget* parent) : QDialog(parent) connect(this->ui.connect_btn, SIGNAL(pressed()), this, SLOT(onConnectMotor())); + connect(this->ui.right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight())); + connect(this->ui.right_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); + connect(this->ui.left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft())); + connect(this->ui.left_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); + + connect(this->ui.move2loc_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc())); + + connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart())); + + connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(onx_rangeMeasurement())); } OneMotorControl::~OneMotorControl() @@ -16,6 +26,31 @@ OneMotorControl::~OneMotorControl() void OneMotorControl::onConnectMotor() { + if (getMotorsConnectionStatus()) + { + QMessageBox msgBox; + msgBox.setText(QString::fromLocal8Bit("马达已连接!")); + msgBox.exec(); + + return; + } + + if (m_multiAxisController != nullptr) + { + disconnect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector)), this, SLOT(display_x_loc(std::vector))); + disconnect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int))); + disconnect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int))); + disconnect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int))); + disconnect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int))); + disconnect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int))); + disconnect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int))); + disconnect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector)), this, SLOT(display_motors_connectivity(std::vector))); + + m_motorThread.quit(); + m_motorThread.wait(); + m_multiAxisController = nullptr; + } + try { FileOperation* fileOperation = new FileOperation(); @@ -29,33 +64,25 @@ void OneMotorControl::onConnectMotor() QMessageBox msgBox; msgBox.setText(QString::fromLocal8Bit("请连接马达!")); msgBox.exec(); + return; } - + m_multiAxisController->moveToThread(&m_motorThread); connect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater())); - connect(this->ui.right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight())); - connect(this->ui.right_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); - connect(this->ui.left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft())); - connect(this->ui.left_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); - - connect(this->ui.move2loc_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc())); - connect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector)), this, SLOT(display_x_loc(std::vector))); connect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int))); connect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int))); connect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int))); - connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart())); connect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int))); - connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(onx_rangeMeasurement())); connect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int))); connect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int))); connect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector)), this, SLOT(display_motors_connectivity(std::vector))); - + m_motorThread.start(); emit testConnectivitySignal(0, 1000); } @@ -73,11 +100,36 @@ void OneMotorControl::display_motors_connectivity(std::vector connectivity) //std::cout << "-----------------------------------"<ui.motor_state_label->setStyleSheet("QLabel{background-color:rgb(0,255,0);}"); + m_xMotorConnectionStatus = true; + + this->ui.motor_state_label->setStyleSheet(R"( + QLabel + { + background-color: #08FACE; + border-radius: 4px; + } + )"); } else { - this->ui.motor_state_label->setStyleSheet("QLabel{background-color:rgb(255,0,0);}"); + m_xMotorConnectionStatus = false; + + this->ui.motor_state_label->setStyleSheet(R"( + QLabel + { + background-color: red; + border-radius: 4px; + } + )"); + } + + if (getMotorsConnectionStatus()) + { + this->ui.connect_btn->setText(QString::fromLocal8Bit("已连接")); + } + else + { + this->ui.connect_btn->setText(QString::fromLocal8Bit("重新连接")); } } @@ -150,15 +202,12 @@ void OneMotorControl::record_white() void OneMotorControl::run() { - if (m_coordinator == nullptr) - { - qRegisterMetaType("OneMotionCapturePathLine"); - m_coordinator = new OneMotionCaptureCoordinator(m_multiAxisController, m_Imager); - connect(this, SIGNAL(start(OneMotionCapturePathLine)), m_coordinator, SLOT(startStepMotion(OneMotionCapturePathLine))); - connect(this, SIGNAL(stopStepMotionSignal()), m_coordinator, SLOT(stopStepMotion())); + qRegisterMetaType("OneMotionCapturePathLine"); + m_coordinator = new OneMotionCaptureCoordinator(m_multiAxisController, m_Imager); + connect(this, SIGNAL(start(OneMotionCapturePathLine)), m_coordinator, SLOT(startStepMotion(OneMotionCapturePathLine))); + connect(this, SIGNAL(stopStepMotionSignal()), m_coordinator, SLOT(stopStepMotion())); - connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete())); - } + connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete(int))); OneMotionCapturePathLine tmp; tmp.speedRecord = ui.speed_lineEdit->text().toDouble(); @@ -172,7 +221,22 @@ void OneMotorControl::stop() emit stopStepMotionSignal(); } -void OneMotorControl::onSequenceComplete() +void OneMotorControl::onSequenceComplete(int state) { emit sequenceComplete(); + + disconnect(this, SIGNAL(start(OneMotionCapturePathLine)), m_coordinator, SLOT(startStepMotion(OneMotionCapturePathLine))); + disconnect(this, SIGNAL(stopStepMotionSignal()), m_coordinator, SLOT(stopStepMotion())); + disconnect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete(int))); + + // Use deleteLater() instead of delete: this slot may have been called directly + // from OneMotionCaptureCoordinator's call stack (direct connection), so deleting + // the object here would cause a crash when execution returns to the destroyed object. + m_coordinator->deleteLater(); + m_coordinator = nullptr; +} + +bool OneMotorControl::getMotorsConnectionStatus() +{ + return m_xMotorConnectionStatus; } diff --git a/HPPA/OneMotorControl.h b/HPPA/OneMotorControl.h index 01e8605..c1ffaf5 100644 --- a/HPPA/OneMotorControl.h +++ b/HPPA/OneMotorControl.h @@ -7,8 +7,9 @@ #include "IrisMultiMotorController.h" #include "fileOperation.h" #include "CaptureCoordinator.h" +#include "MotorWindowBase.h" -class OneMotorControl : public QDialog +class OneMotorControl : public QDialog, public MotorWindowBase { Q_OBJECT @@ -24,6 +25,7 @@ public: void record_dark(); void record_white(); + bool getMotorsConnectionStatus(); public Q_SLOTS: void onConnectMotor(); @@ -38,7 +40,7 @@ public Q_SLOTS: void onxMotorLeft(); void onxMotorStop(); - void onSequenceComplete(); + void onSequenceComplete(int state); signals: void moveSignal(int, bool, double, int); @@ -61,11 +63,13 @@ private: Ui::OneMotorControl_UI ui; QThread m_motorThread; - IrisMultiMotorController* m_multiAxisController; + IrisMultiMotorController* m_multiAxisController = nullptr; OneMotionCaptureCoordinator* m_coordinator = nullptr; ImagerOperationBase* m_Imager; DarkAndWhiteCaptureCoordinator* m_darkCaptureCoordinator = nullptr; DarkAndWhiteCaptureCoordinator* m_whiteCaptureCoordinator = nullptr; + + bool m_xMotorConnectionStatus = false; }; diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp index 964b023..9120fe5 100644 --- a/HPPA/TwoMotorControl.cpp +++ b/HPPA/TwoMotorControl.cpp @@ -18,6 +18,22 @@ TwoMotorControl::TwoMotorControl(QWidget* parent) : QDialog(parent) connect(ui.deleteRecordLine_btn, SIGNAL(clicked()), this, SLOT(onDeleteRecordLine_btn())); connect(ui.saveRecordLine2File_btn, SIGNAL(clicked()), this, SLOT(onSaveRecordLine2File_btn())); connect(ui.readRecordLineFile_btn, SIGNAL(clicked()), this, SLOT(onReadRecordLineFile_btn())); + + connect(this->ui.xmotor_right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight())); + connect(this->ui.xmotor_right_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); + connect(this->ui.xmotor_left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft())); + connect(this->ui.xmotor_left_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); + + connect(this->ui.ymotor_forward_btn, SIGNAL(pressed()), this, SLOT(onyMotorforward())); + connect(this->ui.ymotor_forward_btn, SIGNAL(released()), this, SLOT(onyMotorStop())); + connect(this->ui.ymotor_backward_btn, SIGNAL(pressed()), this, SLOT(onyMotorbackward())); + connect(this->ui.ymotor_backward_btn, SIGNAL(released()), this, SLOT(onyMotorStop())); + + connect(this->ui.move2loc_x_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc())); + connect(this->ui.move2loc_y_pushButton, SIGNAL(pressed()), this, SLOT(onyMove2Loc())); + + connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart())); + connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(on_rangeMeasurement())); } void TwoMotorControl::setImager(ImagerOperationBase* imager) @@ -34,6 +50,9 @@ void TwoMotorControl::setPosFileName(QString posFileName) bool TwoMotorControl::getState() { + if (m_coordinator == nullptr) + return false; + QEventLoop loop; bool tmp = false; bool received = false; @@ -86,29 +105,33 @@ void TwoMotorControl::record_white() void TwoMotorControl::run() { - if (m_coordinator==nullptr) - { - qRegisterMetaType>("QVector"); - m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController, m_Imager); - m_coordinator->moveToThread(&m_coordinatorThread); - connect(&m_coordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater())); - connect(this, SIGNAL(start(QVector)), m_coordinator, SLOT(start(QVector))); - connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop())); - connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int))); - connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(int))); - connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete())); - m_coordinatorThread.start(); - } - if (getState()) { - //std::cout << "已经开始运行,请勿重复点击!!!!!!!!" << std::endl; - QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("已经开始运行,请勿重复点击!!!!!!!!!")); + QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("已经开始运行,请勿重复点击!")); return; } - QVector pathLines; int rowCount = ui.recordLine_tableWidget->rowCount(); + if(rowCount == 0) + { + QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!")); + + emit sequenceComplete(); + return; + } + + qRegisterMetaType>("QVector"); + m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController, m_Imager); + m_coordinator->moveToThread(&m_coordinatorThread); + connect(&m_coordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater())); + connect(this, SIGNAL(start(QVector)), m_coordinator, SLOT(start(QVector))); + connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop())); + connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int))); + connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(int))); + connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete())); + m_coordinatorThread.start(); + + QVector pathLines; //int columnCount = ui.recordLine_tableWidget->columnCount(); for (size_t i = 0; i < rowCount; i++) { @@ -128,7 +151,7 @@ void TwoMotorControl::run() { for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++) { - ui.recordLine_tableWidget->item(i, j)->setBackgroundColor(QColor(240, 240, 240)); + ui.recordLine_tableWidget->item(i, j)->setBackgroundColor(QColor("#0E1C4C")); } } @@ -151,6 +174,30 @@ TwoMotorControl::~TwoMotorControl() void TwoMotorControl::onConnectMotor() { + if (getMotorsConnectionStatus()) + { + QMessageBox msgBox; + msgBox.setText(QString::fromLocal8Bit("马达已连接!")); + msgBox.exec(); + return; + } + + if (m_multiAxisController != nullptr) + { + disconnect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector)), this, SLOT(displayRealTimeLoc(std::vector))); + disconnect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int))); + disconnect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int))); + disconnect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int))); + disconnect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int))); + disconnect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int))); + disconnect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int))); + disconnect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector)), this, SLOT(display_motors_connectivity(std::vector))); + + m_motorThread.quit(); + m_motorThread.wait(); + m_multiAxisController = nullptr; + } + try { FileOperation* fileOperation = new FileOperation(); @@ -164,34 +211,20 @@ void TwoMotorControl::onConnectMotor() QMessageBox msgBox; msgBox.setText(QString::fromLocal8Bit("请连接马达!")); msgBox.exec(); + return; } m_multiAxisController->moveToThread(&m_motorThread); connect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater())); - connect(this->ui.xmotor_right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight())); - connect(this->ui.xmotor_right_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); - connect(this->ui.xmotor_left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft())); - connect(this->ui.xmotor_left_btn, SIGNAL(released()), this, SLOT(onxMotorStop())); - - connect(this->ui.ymotor_forward_btn, SIGNAL(pressed()), this, SLOT(onyMotorforward())); - connect(this->ui.ymotor_forward_btn, SIGNAL(released()), this, SLOT(onyMotorStop())); - connect(this->ui.ymotor_backward_btn, SIGNAL(pressed()), this, SLOT(onyMotorbackward())); - connect(this->ui.ymotor_backward_btn, SIGNAL(released()), this, SLOT(onyMotorStop())); - - connect(this->ui.move2loc_x_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc())); - connect(this->ui.move2loc_y_pushButton, SIGNAL(pressed()), this, SLOT(onyMove2Loc())); - connect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector)), this, SLOT(displayRealTimeLoc(std::vector))); connect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int))); connect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int))); connect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int))); - connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart())); connect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int))); - connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(on_rangeMeasurement())); connect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int))); connect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int))); @@ -223,15 +256,26 @@ void TwoMotorControl::onSequenceComplete() { isWritePosFile = false; fclose(m_posFileHandle); - + + m_coordinatorThread.quit(); + m_coordinatorThread.wait(); + m_coordinator = nullptr; + emit sequenceComplete(); } +bool TwoMotorControl::getMotorsConnectionStatus() +{ + return m_xMotorConnectionStatus && m_yMotorConnectionStatus; +} + void TwoMotorControl::display_motors_connectivity(std::vector connectivity) { //std::cout << "-----------------------------------"<ui.xMotorStateLabel->setStyleSheet(R"( QLabel { @@ -242,6 +286,8 @@ void TwoMotorControl::display_motors_connectivity(std::vector connectivity) } else { + m_xMotorConnectionStatus = false; + this->ui.xMotorStateLabel->setStyleSheet(R"( QLabel { @@ -253,6 +299,8 @@ void TwoMotorControl::display_motors_connectivity(std::vector connectivity) if (connectivity[1]) { + m_yMotorConnectionStatus = true; + this->ui.yMotorStateLabel->setStyleSheet(R"( QLabel { @@ -263,6 +311,8 @@ void TwoMotorControl::display_motors_connectivity(std::vector connectivity) } else { + m_yMotorConnectionStatus = false; + this->ui.yMotorStateLabel->setStyleSheet(R"( QLabel { @@ -271,6 +321,15 @@ void TwoMotorControl::display_motors_connectivity(std::vector connectivity) } )"); } + + if(getMotorsConnectionStatus()) + { + this->ui.connect_btn->setText(QString::fromLocal8Bit("已连接")); + } + else + { + this->ui.connect_btn->setText(QString::fromLocal8Bit("重新连接")); + } } void TwoMotorControl::onxMotorRight() diff --git a/HPPA/TwoMotorControl.h b/HPPA/TwoMotorControl.h index 2f58984..44b8f8b 100644 --- a/HPPA/TwoMotorControl.h +++ b/HPPA/TwoMotorControl.h @@ -8,12 +8,11 @@ #include "IrisMultiMotorController.h" #include "fileOperation.h" #include "CaptureCoordinator.h" +#include "MotorWindowBase.h" #define PI 3.1415926 - - -class TwoMotorControl : public QDialog +class TwoMotorControl : public QDialog, public MotorWindowBase { Q_OBJECT @@ -26,6 +25,8 @@ public: void record_dark(); void record_white(); + + bool getMotorsConnectionStatus(); private: ImagerOperationBase* m_Imager; @@ -35,6 +36,8 @@ private: QString m_posFileName; FILE* m_posFileHandle; + bool m_xMotorConnectionStatus = false; + bool m_yMotorConnectionStatus = false; public Q_SLOTS: void onConnectMotor(); @@ -94,5 +97,5 @@ private: DarkAndWhiteCaptureCoordinator* m_whiteCaptureCoordinator = nullptr; QThread m_motorThread; - IrisMultiMotorController* m_multiAxisController; + IrisMultiMotorController* m_multiAxisController = nullptr; }; diff --git a/HPPA/twoMotorControl.ui b/HPPA/twoMotorControl.ui index 5e4f11b..61cda19 100644 --- a/HPPA/twoMotorControl.ui +++ b/HPPA/twoMotorControl.ui @@ -367,7 +367,7 @@ QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { /* 表格整体 */ QTableWidget { background-color: #0E1C4C; - color: #ACCDFF; + color: white; gridline-color: #4B60A6; border: 1px solid #4B60A6; } @@ -377,11 +377,6 @@ QTableWidget QAbstractScrollArea::viewport { background-color: #0E1C4C; } -/* 单元格 */ -QTableWidget::item { - background-color: #0E1C4C; - color: #ACCDFF; -} /* 表头 */ QHeaderView::section {