#include "lpMainWin.h" #include "quserinfo_global.h" #include #include #include "qmysplashscreen.h" #include "InfoFile.h" #include "WheelCtrl.h" #include "QWorkMgrCtlr.h" #include "qworkmgrui.h" #include "IWheelModel.h" #include #include "qnettickthread.h" #include "QMessageBox" #include "ChannelInfo.h" #include "HubBase.h" #include #include #include "saveimgthread.h" #include "lpGlobalData.h" #include "qpulpewidget.h" #include "QZkJsonParser.h" #include #include "lpCryptokey.h" #define VERSION_HUB "3.0.3.1" #define VERSION_ALG "3.0.1.6" #define UPDATE_TIME "2022-05-19" #define WHEELHIGHTTHRESH 260.0 //轮毂高度阈值,当轮毂高度大于这个值时,启用相机升高的直径算法 #define CAMERAUPHEIGHT 254.0 //相机上升高度,默认10英寸 #pragma execution_character_set("utf-8") lpMainWin::lpMainWin(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); {//加载语言设置 QSettings languageSetting("hubdetect.ini", QSettings::IniFormat); QString strLanguage = languageSetting.value("language", "Chinese").toString(); SetLanguage(strLanguage); } this->setWindowIcon(QIcon(":/image/leaper")); QMySplashScreen m_screen; m_screen.show(); qRegisterMetaType("TimeStruct"); m_screen.ShowMsg(tr("加载必要模块.....")); onInitCoreCtrl(); onInitAbout(); { QGridLayout *pLayout = new QGridLayout(ui.cam_win_1); m_ImgViewer = new RoiImgViewer(ui.cam_win_1); m_ImgViewer->setObjectName("Imageview"); pLayout->addWidget(m_ImgViewer); ui.cam_win_1->setLayout(pLayout); } { connect(ui.action_userManager, SIGNAL(triggered()), this, SLOT(onActionClicked()));//用户管理 connect(ui.action_Login, SIGNAL(triggered()), this, SLOT(onActionClicked()));//用户登录 connect(ui.action_about, SIGNAL(triggered()), this, SLOT(onActionClicked()));//关于 connect(ui.action_setting_ip, SIGNAL(triggered()), this, SLOT(onActionClicked()));//IP设置 connect(ui.action_cali_raster, SIGNAL(triggered()), this, SLOT(onActionClicked()));//光栅尺 connect(ui.action_setting_ban, SIGNAL(triggered()), this, SLOT(onActionClicked()));//班次设置 connect(ui.action_debug, SIGNAL(triggered()), this, SLOT(onActionClicked()));//调试助手 connect(ui.action_connect_mode, SIGNAL(triggered()), this, SLOT(onActionClicked()));//连接模式 connect(ui.action_checkdata, SIGNAL(triggered()), this, SLOT(onActionClicked()));//历史数据查看页面 connect(ui.action_modelmgr, SIGNAL(triggered()), this, SLOT(onActionClicked()));//模板管理 connect(ui.action_algParam, SIGNAL(triggered()), this, SLOT(onActionClicked()));//算法参数设置 connect(ui.action_register, SIGNAL(triggered()), this, SLOT(onActionClicked()));//注册页面 connect(ui.actionSystemSeting, SIGNAL(triggered()), this, SLOT(onActionClicked()));//系统参数设置 connect(ui.actioncamSetting, SIGNAL(triggered()), this, SLOT(onActionClicked()));//相机设置 connect(ui.btn_start_detect, SIGNAL(clicked()), this, SLOT(onButtonClicked()));//开始检测 停止检测 connect(ui.btn_clear_data, SIGNAL(clicked()), this, SLOT(onButtonClicked()));//清空统计 ui.action_userManager->setVisible(false);//默认用户管理菜单隐藏 只有相应权限才能显示 //下拉菜单 布局 工具菜单 配置相关系统设置菜单 QMenu *pToolMenu = new QMenu(this); pToolMenu->addAction(ui.actioncamSetting); pToolMenu->addAction(ui.action_cali_raster); pToolMenu->addAction(ui.action_setting_ip); pToolMenu->addAction(ui.action_setting_ban); pToolMenu->addAction(ui.actionSystemSeting); pToolMenu->addAction(ui.action_algParam); pToolMenu->addAction(ui.action_debug); QToolButton* pbutton = new QToolButton(this); pbutton->setMenu(pToolMenu); pbutton->setIcon(QIcon(":/ToolBarPic/ToolButon")); pbutton->setText(tr("工具")); pbutton->setToolTip(tr("工具")); pbutton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); pbutton->setPopupMode(QToolButton::InstantPopup); ui.mainToolBar->addWidget(pbutton); //帮助 下拉菜单 QMenu *pHelpMenu = new QMenu(this); pHelpMenu->addAction(ui.action_about); pHelpMenu->addAction(ui.action_register); QToolButton* pHelptool = new QToolButton(this); pHelptool->setMenu(pHelpMenu); pHelptool->setIcon(QIcon(":/ToolBarPic/ToolBarpic/help.png")); pHelptool->setText(tr("帮助")); pHelptool->setToolTip(tr("帮助")); pHelptool->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); pHelptool->setPopupMode(QToolButton::InstantPopup); ui.mainToolBar->addWidget(pHelptool); ui.mainToolBar->addSeparator(); m_pLabelInfo = new QLabel(this); m_pLabelInfo->setText(tr("本系统未注册激活")); m_pLabelInfo->setStyleSheet("font: bold 14px; color: red;"); ui.mainToolBar->addWidget(m_pLabelInfo); } {//状态栏初始化配置 m_pLbCurrentTime = new QLabel(tr("系统时间")); m_pLbBanci = new QLabel(tr("班次信息")); m_pLbDetectState = new QLabel(tr("检测状态")); m_pLbUser = new QLabel(tr("用户:")); m_pLbPLCConnect = new QLabel(tr("PLC连接")); QFont m_font; m_font.setBold(true); m_font.setPixelSize(12); m_pLbCurrentTime->setFont(m_font); m_pLbCurrentTime->setMinimumHeight(40); m_pLbCurrentTime->setMinimumWidth(200); m_pLbCurrentTime->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pLbUser->setMinimumWidth(100); m_pLbUser->setFont(m_font); m_pLbUser->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pLbBanci->setMinimumWidth(100); m_pLbBanci->setFont(m_font); m_pLbBanci->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pLbDetectState->setMinimumWidth(200); m_pLbDetectState->setFont(m_font); m_pLbDetectState->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pLbPLCConnect->setMinimumWidth(200); m_pLbPLCConnect->setFont(m_font); m_pLbPLCConnect->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pLbUser->setFont(m_font); m_pLbUser->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); ui.statusBar->addWidget(m_pLbDetectState, 1); ui.statusBar->addWidget(m_pLbPLCConnect, 1); ui.statusBar->addWidget(m_pLbUser,2); ui.statusBar->addWidget(m_pLbBanci,2); ui.statusBar->addPermanentWidget(m_pLbCurrentTime,5); } //加载用户管理模块 loadUserModel(); //初始化模型管理模块 {//总逻辑处理模块 核心管理 m_pCtrl = new WheelCtrl(QCoreApplication::applicationDirPath(), &m_screen); pWorkCtrl = new QWorkMgrCtlr(m_pCtrl);//工单管理模块 pWorkCtrl->readManageFile(); m_pworkUI = new QWorkMgrUI(pWorkCtrl, m_pCtrl);//工单管理UI模块 m_pworkUI->InitUI(); connect(m_pworkUI, SIGNAL(sgUpdatedefect()), this, SLOT(onUpdateDefect())); m_pModelMgrDlg = new QModelMgrDlg(m_pCtrl);//模板管理UI //当某个模板加入训练或者不加入训练时修改原来工作单中的模板信息 connect(m_pModelMgrDlg, SIGNAL(sgModifyModel(QString)), this, SLOT(modWorkMgr(QString))); connect(m_pModelMgrDlg, SIGNAL(sgUpdatedefect()), this, SLOT(onUpdateDefect())); m_pDebugDlg = new QDebugDlg();//调试界面 connect(m_pDebugDlg, SIGNAL(sgTriggerCam()), this, SLOT(onTriggerCam())); m_pDebugDlg->onSetCtrl(m_pCtrl); m_pTimerMgrDlg = new QTimeMgrDlg();//班次管理 m_pTimerMgrDlg->onSetCtrlPtr(m_pCtrl); m_pSystemSettingDlg = new QSystemSettingDlg();//系统设置 m_CamSettingDlg = new QCamSettingDlg(); m_CamSettingDlg->setCoreCtrlPtr(m_pCoreCtrl); connect(m_pSystemSettingDlg, SIGNAL(sgChangeLanguage(QString)), this, SLOT(onLanguageChange(QString))); connect(m_pSystemSettingDlg, SIGNAL(sgChangePLCParam()), this, SLOT(onChangePLCParam())); connect(m_pSystemSettingDlg, SIGNAL(sgParamChange()), this, SLOT(onUpdateUI())); //历史检测图像缩略图 m_pixMapList = new QPixmapListBar(ui.tp_main_tabWidget); ui.tp_main_tabWidget->insertTab(0, m_pixMapList, tr("历史")); ui.tp_main_tabWidget->setCurrentIndex(0); m_pAlgParamDlg = new QAlgParamDlg();//算法参数设置页面 connect(m_pAlgParamDlg, SIGNAL(sgParamChange()), this, SLOT(onUpdateUI())); connect(m_pAlgParamDlg, SIGNAL(sgExpsChange()), this, SLOT(onUpdateExposureSetting())); } { /*发送模板库线程*/ SendModelLibTask = new QMyThread(); SendModelLibTask->setUser(true); TaskFunc KuTaskFunc = std::bind(&lpMainWin::SendModelKuTskFun,this); SendModelLibTask->loadfunc(KuTaskFunc); SendTiskTsk = new QMyThread(); TaskFunc TickFunc = std::bind(&lpMainWin::SendTickTskFun, this); SendTiskTsk->loadfunc(TickFunc); m_screen.ShowMsg(tr("系统初始化完成...")); } { onSetModel(); /*网络通信加载*/ m_pNet = ((WheelCtrl*)m_pCtrl)->getNet(); connect(m_pNet, SIGNAL(sgShow2UI(QString, bool)), this, SLOT(onTcpConnet(QString, bool)));//net connect(m_pNet, SIGNAL(sgClientConnect(QString, bool)), this, SLOT(onClientConnect(QString, bool)));//net //connect(m_pNet, SIGNAL(sgRecv(const QString &)), this, SLOT(onTcpRecv(const QString &)));// net显示 connect(m_pNet, SIGNAL(sgThickness(double)), this, SLOT(onThickness(double)));//xy height connect(m_pNet, SIGNAL(sgRecvDetectState(int, int)), this, SLOT(onDetectStateRecv(int, int)));//xy check connect(m_pNet, SIGNAL(sgClearRev(bool)), this, SLOT(onClearLibRev(bool)));//xy clearlib connect(m_pNet, SIGNAL(sgPulseRev()), this, SLOT(onPulseRev())); // connect(m_pNet, SIGNAL(sgResultRev()), this, SLOT(onResultRev())); connect(m_pNet, SIGNAL(sgRecvTrigPara()), this, SLOT(onRecvTrigPara())); connect(m_pNet, SIGNAL(sgReadDetectState(int, QString)), this, SLOT(onReadDetectState(int, QString))); connect(m_pNet, SIGNAL(sgReadDetectStateASK()), this, SLOT(onReadDetectStateASK())); connect(m_pNet, SIGNAL(sgCameraTrig(int,double)), this, SLOT(onTrigRecv(int,double))); connect(m_pNet, SIGNAL(sgServerState(QString, int, bool)), this, SLOT(onServerState(QString, int, bool))); connect(m_pNet, SIGNAL(sgShutDownComputer()), this, SLOT(onShutDownComputer())); connect(m_pNet, SIGNAL(sgLibRev(bool)), SendModelLibTask, SLOT(WaitSingleIn(bool)));//xy lib // connect(m_pNet, SIGNAL(sgChangeOnlineState(int)), m_pUi, SLOT(onSwitchOnlineModel(int)));//强制在线 离线 } { connect(&m_PulseTimer, SIGNAL(timeout()), this, SLOT(onPulseTimer()));//心跳包 connect(&m_wfPulseTimer, SIGNAL(timeout()), this, SLOT(onwfPulseTimer()));//心跳包 connect(&m_ThicknessTimer, SIGNAL(timeout()), this, SLOT(onThicknessTimer()));// 厚度查询 connect(&m_ReadLibTimer, SIGNAL(timeout()), this, SLOT(onSendReadOnlineLib())); connect(this, SIGNAL(sgTickTsk()), this, SLOT(onPulseTimer())); connect(this, SIGNAL(sgShowMsg(QString, bool)), this, SLOT(onTcpConnet(QString, bool))); connect(this, SIGNAL(sgTaskSendModels(int, QString, double, double)), this, SLOT(onTaskSendModels(int, QString, double, double)));//用于发送莫板库 connect(this, SIGNAL(sgTskSendDetectState(int, QString, int)), this, SLOT(onTaskSendDetectState(int, QString, int)));//离线检测发送 用于发送检测状态 connect(this, SIGNAL(sgTskSendCheck(int, int, QString)), this, SLOT(onTaskCheck(int, int, QString)));//在线检测状态查询 用于查询线程 // connect(this, SIGNAL(sgCheckEnd()), this, SLOT(onCheckEnd())); connect(this, SIGNAL(sgShowImgState(QString)), this, SLOT(onShowImgState(QString))); connect(this, SIGNAL(sgGetImg()), this, SLOT(onGetImg())); connect(this, SIGNAL(sgShowMsgdlg(QString)), this, SLOT(onShowMsg(QString))); connect(this, SIGNAL(sgSendDisLib(int, QString)), this, SLOT(onSendDisLib(int, QString))); connect(this, SIGNAL(sgSendDisLibDone()), this, SLOT(onSendDisLibDone())); connect(this, SIGNAL(sgShowChannelRes(QString)), this, SLOT(onShowChannel(QString))); } { //???做什么用的 pTickThread = new QThread(this); QNetTickThread *pNetTick = new QNetTickThread; pNetTick->setNetPtr(m_pNet); pNetTick->moveToThread(pTickThread); connect(pTickThread, &QThread::finished, pNetTick, &QObject::deleteLater); connect(this, SIGNAL(sgNetData(int, QVariantMap)), pNetTick, SLOT(doWork(int, QVariantMap))); connect(pNetTick, SIGNAL(resultReady(int, QVariantMap)), m_pNet, SLOT(onSendDataByType(int, QVariantMap))); pTickThread->start(); } { m_pTableCheck = new ModelsView(ui.tableview_checkstate, m_pCtrl->getAllModelMapPtr()); m_pTableCheck->setEnable(false); connect(m_pCtrl, SIGNAL(sgModelChanged()), m_pTableCheck, SLOT(updateModels())); QStringList strList = forDefectList; if (!strList.contains("NG")) strList.append("NG"); m_pTableCheck->setModelList(strList); } //m_PulseTimer.start(1000); connect(this, SIGNAL(sgAutoExposure()), this, SLOT(onAutoExposure())); connect(this, SIGNAL(sgShowRatioVal(double)), this, SLOT(onShowRatioVal(double))); //自动曝光参数 QString strPath = QApplication::applicationDirPath(); readExposureTimeConfig(strPath); onUpdateUI(); //注册码相关 lpGlobalData::instance()->m_bCheckLinese = lpCheckKey::instance()->checkLinese(); m_pCheckLineseUI = new QCryptokeyUI(); connect(m_pCheckLineseUI, SIGNAL(sgRegisterFinish(bool)), this, SLOT(onLineseCheck(bool))); onLineseCheck(lpGlobalData::instance()->m_bCheckLinese); onUpdateByLevel(0); /*启动之后就一直发送心跳包和厚度查询*/ if (DetectState::instance()->m_AutoSendTick2Net) { SendTiskTsk->setSleepTime(1000); SendTiskTsk->start(); } //if (DetectState::instance()->m_StartAndDetect == 1)//m_sysType 表示万丰科技的 /* { QTimer::singleShot(3000, [&]() { ui.btn_start_detect->setText(tr("停止检测")); DetectState::instance()->IsDetect = true; m_pCtrl->onStart(); }); } */ if (DetectState::instance()->m_AutoSendTick2COM) m_wfPulseTimer.start(1000); m_timerID = startTimer(1000); m_timerID_Init = startTimer(1000); QTimer::singleShot(1000, m_pNet, SLOT(onOpenServer()));//延迟2s打开网络TCP服务 } lpMainWin::~lpMainWin() { m_timer.stop(); if (m_VecTranPtr.size() > 0) { while (m_VecTranPtr.size()) { QTranslator *pTrans = m_VecTranPtr.takeFirst(); qApp->removeTranslator(pTrans); delete pTrans; } } if (m_pUserCtrl) { delete m_pUserCtrl; m_pUserCtrl = NULL; } if (SendModelLibTask) { qDebug() << "delete SendModelLibTak"; if (SendModelLibTask->isRunning()) SendModelLibTask->stop(); SendModelLibTask->wait(50); delete SendModelLibTask; SendModelLibTask = NULL; qDebug() << "delete SendModelLibTak end"; } if (SendTiskTsk) { qDebug() << "delete SendTiskTsk"; if (SendTiskTsk->isRunning()) SendTiskTsk->stop(); SendTiskTsk->wait(50); delete SendTiskTsk; SendTiskTsk = NULL; qDebug() << "delete SendTiskTsk end"; } if (pTickThread) { qDebug() << "delete pTickThread"; if (pTickThread->isRunning()) { pTickThread->quit(); pTickThread->wait(50); } delete pTickThread; pTickThread = NULL; qDebug() << "delete pTickThread end"; } { if (m_pLbCurrentTime) { delete m_pLbCurrentTime; m_pLbCurrentTime = nullptr; } if (m_pLbBanci) { delete m_pLbBanci; m_pLbBanci = nullptr; } if (m_pLbDetectState) { delete m_pLbDetectState; m_pLbDetectState = nullptr; } if (m_pLbUser) { delete m_pLbUser; m_pLbUser = nullptr; } if (m_pLbPLCConnect) { delete m_pLbPLCConnect; m_pLbPLCConnect = nullptr; } } if (m_pCtrl) { delete m_pCtrl; m_pCtrl = nullptr; } if (pWorkCtrl) { delete pWorkCtrl; pWorkCtrl = nullptr; } if (m_pworkUI) { delete m_pworkUI; m_pworkUI = nullptr; } if (m_pModelMgrDlg) { delete m_pModelMgrDlg; m_pModelMgrDlg = nullptr; } if (m_pDebugDlg) { delete m_pDebugDlg; m_pDebugDlg = nullptr; } if (m_pTimerMgrDlg) { delete m_pTimerMgrDlg; m_pTimerMgrDlg = nullptr; } if (m_pSystemSettingDlg) { delete m_pSystemSettingDlg; m_pSystemSettingDlg = nullptr; } if (m_CamSettingDlg) { delete m_CamSettingDlg; m_CamSettingDlg = nullptr; } if (m_pCheckLineseUI) { delete m_pCheckLineseUI; m_pCheckLineseUI = nullptr; } if (m_pLabelInfo) { delete m_pLabelInfo; m_pLabelInfo = nullptr; } if (m_pAlgParamDlg) { delete m_pAlgParamDlg; m_pAlgParamDlg = nullptr; } if (m_ImgViewer) { delete m_ImgViewer; m_ImgViewer = nullptr; } if (m_pixMapList) { delete m_pixMapList; m_pixMapList = nullptr; } if (m_pDllCoreCtrl) { delete m_pDllCoreCtrl; m_pDllCoreCtrl = nullptr; } } //核心corctrl模块 包括相机算法等相关模块 bool lpMainWin::onInitCoreCtrl() { //load coretrl if (NULL == m_pDllCoreCtrl) { m_pDllCoreCtrl = new CDllCoreCtrl(QStringList(), nullptr); if (NULL == m_pDllCoreCtrl) { return false; } m_pCoreCtrl = m_pDllCoreCtrl->m_pCoreCtrl; FuncCallBack_VarInt getVarfunc = std::bind(&lpMainWin::IGetVariantById, this, std::placeholders::_1); m_pCoreCtrl->IRegisterGetVariant(getVarfunc); FuncCallBack_StrMap strMapfunc = std::bind(&lpMainWin::IVariantMapToUI, this, std::placeholders::_1, std::placeholders::_2); m_pCoreCtrl->IRegisterResultCallBack(strMapfunc); FuncCallBack_StrImg strImgfunc = std::bind(&lpMainWin::INewCameraImage, this, std::placeholders::_1, std::placeholders::_2); m_pCoreCtrl->IRegisterImageCallBack(strImgfunc); QStringList s = m_pCoreCtrl->ICameraKeys(); if(m_pCoreCtrl->ICameraKeys().size()>0) m_camKey = m_pCoreCtrl->ICameraKeys().first(); return true; } return false; } void lpMainWin::loadUserModel() { //userctrel #ifdef _DEBUG QLibrary lib("QUserInfod"); #else QLibrary lib("QUserInfo"); #endif _UserCtrlCreate func = (_UserCtrlCreate)lib.resolve("UserCtrlCreate"); if (func) { m_pUserCtrl = func(); connect(m_pUserCtrl, SIGNAL(sgCurrentUserInfo(QString, int, int)), this, SLOT(onLogInOut(QString, int, int))); } } /*****************************系统语言设置*****************************/ void lpMainWin::SearchQmFile(const QString & strDir) { QDir dir(strDir); if (!dir.exists()) { return; } dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); dir.setSorting(QDir::DirsFirst); // 文件夹优先 // 转换成一个List QFileInfoList list = dir.entryInfoList(); if (list.size() < 1) { return; } int i = 0; do { QFileInfo fileInfo = list.at(i); QString tt = fileInfo.fileName(); // 如果是文件夹 bool bisDir = fileInfo.isDir(); if (bisDir) { SearchQmFile(fileInfo.filePath()); } else { bool bQm = fileInfo.fileName().endsWith(".qm"); SetTranslator(fileInfo.filePath()); } i++; } while (i < list.size()); } void lpMainWin::SetTranslator(const QString strPath) { if (strPath.isEmpty()) { return; } QTranslator *pTrans = new QTranslator; // 如果加载成功 if (pTrans->load(strPath)) { qApp->installTranslator(pTrans); m_VecTranPtr.append(pTrans); } else { delete pTrans; pTrans = NULL; } } void lpMainWin::SetLanguage(QString strLangage) { QString strDirPath = QString(QCoreApplication::applicationDirPath() + "/language/"); QString translatorFileName = strLangage; if (!translatorFileName.isEmpty()) { if (m_VecTranPtr.size() > 0) { while (m_VecTranPtr.size()) { QTranslator *pVa = m_VecTranPtr.takeFirst(); qApp->removeTranslator(pVa); delete pVa; pVa = NULL; } } QLocale::setDefault(QLocale(translatorFileName)); QString transDir = strDirPath + translatorFileName; SearchQmFile(transDir); } } /*****************************系统语言设置 END*****************************/ /*主线程接收图像*/ void lpMainWin::INewCameraImage(const QString& camKey, QImage img) { if (m_ImgViewer) { int widgetWidth = m_ImgViewer->width(); int imgWidth = img.width(); float scalew = (widgetWidth*1.0) / (imgWidth*1.0); int widgetHeight = m_ImgViewer->height(); int imgHeight = img.height(); float scaleh = (widgetHeight*1.0) / (imgHeight*1.0); float minScale = scalew < scaleh ? scalew : scaleh; m_ImgViewer->setInitScale(minScale-0.01); m_ImgViewer->setImg(img); } if (m_CamSettingDlg) { if (m_CamSettingDlg->isHidden()) return; m_CamSettingDlg->onShowImage(img); } } /*多线程发送算法结果*/ void lpMainWin::IVariantMapToUI(const QString& camKey, const QVariantMap& vMap) { try { m_glbalRatio = 0; emit(sgShowImgState(tr("显示识别结果"))); Result2Ui *pResult = (Result2Ui*)vMap.value("result").toLongLong(); double vRatioVal = vMap.value("ratioVal").toDouble(); if (pResult == nullptr) { pResult = new Result2Ui(); } emit sgShowRatioVal(vRatioVal); // 当没抠出轮毂和NG时自动调整曝光时间重新拍照,最多调整的次数为5次 if (m_autoExposureSwitch) { if (vMap.contains("noCircle")) { if (m_exposureTimeCount == 0) { int curExposure = getCurExposureTime(); if (curExposure != m_exposureTimeArray[0]) { emit(sgShowMsgdlg(tr("当前曝光时间未识别到轮毂!"))); emit sgAutoExposure(); m_exposureTimeCount++; delete pResult; return; } } m_exposureTimeCount++; if (m_exposureTimeCount >= m_exposureTimeArray.size()) { emit(sgShowMsgdlg(tr("调整5次曝光时间后依然未能识别到轮毂!"))); } else { emit(sgShowMsgdlg(tr("当前曝光时间未识别到轮毂!"))); emit sgAutoExposure(); delete pResult; return; } } bool ngFlag = (pResult->m_strModel.isEmpty()) && (m_exposureTimeCount < m_exposureTimeArray.size()); if (ngFlag) { if (m_exposureTimeCount == 0) { int curExposure = getCurExposureTime(); if (curExposure != m_exposureTimeArray[0]) { emit(sgShowMsgdlg(tr("当前曝光时间未识别到轮毂!"))); emit sgAutoExposure(); pResult->m_strModel = "NG"; saveImage(pResult); m_exposureTimeCount++; delete pResult; return; } } m_exposureTimeCount++; if (m_exposureTimeCount >= m_exposureTimeArray.size()) { emit(sgShowMsgdlg(tr("调整5次曝光时间后依然未能识别到轮毂!"))); } else { emit(sgShowMsgdlg(tr("当前曝光时间未识别到轮毂!"))); emit sgAutoExposure(); pResult->m_strModel = "NG"; saveImage(pResult); delete pResult; return; } } } if (vMap.contains("error")) { m_exposureTimeCount = 0; emit(sgShowMsgdlg(tr("相机图像和背景图不一样,请更换检测背景!"))); return; } onShowResult(pResult); if (m_pDebugDlg) { m_pDebugDlg->onShowResult(pResult); } saveImage(pResult); if (m_autoExposureSwitch) { m_exposureTimeCount = 0; int exp = m_exposureTimeArray[m_exposureTimeCount]; m_pCoreCtrl->ISetExposureTime(m_camKey, exp); } static int ErrorNum = 0; if (m_pNet) { if (pResult->m_strModel == "NG") { SendResultBee(LIGHT_REDBEE, 1); SendResultBee(LIGHT_BEE, 1); ErrorNum++; } else { SendResultBee(LIGHT_GREENBEE, 1); ErrorNum = 0; } if (ErrorNum >= 3) { QString str = tr("警告!!!连续出现%1个未识别型号").arg(ErrorNum); if (DetectState::instance()->IsDetect == false) str += tr(",未开启检测功能造成的"); m_pCtrl->addLog(str, emTypeWaring); SendResultBee(LIGHT_REDBEE, 3); SendResultBee(LIGHT_BEE, 3); } } if (DetectState::instance()->m_SendDetectStr2Net) SendResultStr2PLC(pResult);//发送检测结果字符到PLC if (DetectState::instance()->m_SendChannelRes2COM) SendResultChannelCOM(pResult);//发送检测结果通道到串口 if (DetectState::instance()->m_SendChannelRes2Net>0 && DetectState::instance()->m_IsUseChannel>0) SendResultChannel2PLC(pResult);//发送检测结果通道到PLC m_pCtrl->saveResult(pResult); delete pResult; } catch(...) { qWarning() << "dump result " << __FUNCTION__; } } /*多线程获取算法参数*/ QVariant lpMainWin::IGetVariantById(int id) { m_nDiffTrigNum--;//进入到这里 表示获取到了图片 qWarning() << "Alg get An Image:" << "(" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz") << ")"; emit(sgShowImgState(tr("获得图像,正在计算中..."))); emit(sgGetImg()); qDebug() << "get one Pic ,id=" << id; if (DetectState::instance()->m_showThressList == 1) { QString str = m_pCtrl->getThicknessStr(); emit(sgShowMsg(str, true)); } QVariantMap vMap; int nThickness = 0; if (DetectState::instance()->m_IsUseRaster == 0) nThickness = m_nWfThress; else { nThickness = m_pCtrl->getThickness(); if (nThickness > WHEELHIGHTTHRESH) { nThickness -= CAMERAUPHEIGHT; } } vMap.insert("thickness", QVariant(nThickness)); double dDiameter;// = (-794.25 * nThickness / 1000000.0 + 0.775960); dDiameter = (DetectState::instance()->m_k * nThickness + DetectState::instance()->m_b); vMap.insert("d2h", dDiameter); vMap.insert("useThickness", DetectState::instance()->bUseThickness); vMap.insert("useDiameter", DetectState::instance()->bUseDiameter); vMap.insert("IsCutImg", DetectState::instance()->m_UseCutImg); vMap.insert("Ratio", m_glbalRatio);//偏距系数 vMap.insert("Threshold", DetectState::instance()->m_algParam.m_AlgThres);//算法图像阈值 vMap.insert("useBackground", DetectState::instance()->m_algParam.m_UseBackground > 0 ? true:false);//使用背景图 vMap.insert("RatioType", DetectState::instance()->m_algParam.m_RatioDetectType);//偏距检测模式 启用方式 vMap.insert("bEqual", DetectState::instance()->m_algParam.m_bUseEqual);//使用使用图像增强 vMap.insert("filterSize", DetectState::instance()->m_algParam.m_filterSize);//过滤圆大小 vMap.insert("Circle_ACThres", DetectState::instance()->m_algParam.m_Circle_ACThres);// vMap.insert("Circle_EdgeWidth", DetectState::instance()->m_algParam.m_Circle_EdgeWidth);// vMap.insert("Circle_Polarity", DetectState::instance()->m_algParam.m_Circle_Polarity);// //传递模板库指针 void* address = (void*)m_pCtrl->getAllModelMapPtr(); long long varadr = (long long)address; vMap.insert("modelMap", varadr); //传递检测模板名指针 void* pdefectList = (void*)&forDefectList; long long val = (long long)pdefectList; vMap.insert("defectList", val); qDebug() << "end get one pic" << id; if (DetectState::instance()->m_showThressValue == 1) { QString str = QString("thickness value = %1,dDiameter value = %2").arg(nThickness).arg(dDiameter); emit(sgShowMsg(str, true)); } return vMap; } Q_SLOT void lpMainWin::onLogInOut(QString strName, int level, int state) { lpGlobalData::instance()->m_curUser = strName; lpGlobalData::instance()->m_level = level; if (state == 0) { m_pCtrl->setUser(strName, level); ui.action_Login->setText(tr("注 销")); } else { m_pCtrl->setUser(strName, level); ui.action_Login->setText(tr("登 录")); } onUpdateByLevel(level); if (m_pModelMgrDlg) { m_pModelMgrDlg->onUserLevel(level); } } /*菜单栏所有事件*/ Q_SLOT void lpMainWin::onActionClicked() { QString strObj = sender()->objectName(); if ("action_userManager" == strObj) { /*用户管理*/ if (m_pUserCtrl) { m_pUserCtrl->ShowUserMgrDlg(this); } else { QMessageBox infobox(QMessageBox::Information, tr("提示"), tr("该功能未启用."), QMessageBox::Yes, this); infobox.setWindowIcon(QIcon(":/image/leaper")); infobox.setButtonText(QMessageBox::Yes, tr("确认")); infobox.exec(); } } else if ("action_Login" == strObj) { /*用户登陆*/ if (m_pUserCtrl) { if (m_pUserCtrl->getLoginState() == EM_LOGIN) { QMessageBox infobox(QMessageBox::Information, tr("提示"), QString("%1 %2 ?").arg(tr("你确定要注销")).arg(m_pUserCtrl->CurUser()), QMessageBox::Yes | QMessageBox::No, this); infobox.setWindowIcon(QIcon(":/image/leaper")); infobox.setButtonText(QMessageBox::Yes, tr("确认")); infobox.setButtonText(QMessageBox::No, tr("取消")); if (infobox.exec() == QMessageBox::Yes) { m_pUserCtrl->LogOutUser(); } } else { m_pUserCtrl->CheckLogin(this); } } else { QMessageBox infobox(QMessageBox::Information, tr("提示"), tr("该功能未启用."), QMessageBox::Yes, this); infobox.setWindowIcon(QIcon(":/image/leaper")); infobox.setButtonText(QMessageBox::Yes, tr("确认")); infobox.exec(); } } else if ("action_about" == strObj) { m_aboutDlg.setWindowIcon(QIcon(":/image/leaper")); m_aboutDlg.setParent(this); m_aboutDlg.setWindowTitle(tr("关于")); m_aboutDlg.setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_aboutDlg.setWindowModality(Qt::ApplicationModal); m_aboutDlg.setAttribute(Qt::WA_ShowModal, true); m_aboutDlg.show(); } else if ("action_setting_ip" == strObj) { if(m_pNet) m_pNet->onShowIpDlg(this); } else if ("action_cali_raster" == strObj) {//光栅测试 if (m_pCtrl) { m_pCtrl->onShowRaster(this); } } else if ("action_setting_ban" == strObj) { if (m_pTimerMgrDlg) { m_pTimerMgrDlg->setParent(this); m_pTimerMgrDlg->setWindowTitle(tr("班次管理")); m_pTimerMgrDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_pTimerMgrDlg->setWindowIcon(QIcon(":/image/leaper")); m_pTimerMgrDlg->setWindowModality(Qt::ApplicationModal); m_pTimerMgrDlg->setAttribute(Qt::WA_ShowModal, true); m_pTimerMgrDlg->show(); } } else if ("action_debug" == strObj) { if (m_pDebugDlg) { m_pDebugDlg->setParent(this); m_pDebugDlg->setWindowTitle(tr("调试工具")); m_pDebugDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_pDebugDlg->setWindowIcon(QIcon(":/image/leaper")); //m_pDebugDlg->setWindowModality(Qt::ApplicationModal); //m_pDebugDlg->setAttribute(Qt::WA_ShowModal, true); m_pDebugDlg->show(); } } else if ("action_connect_mode" == strObj) {//检测模板勾选 if (m_pworkUI) { m_pworkUI->setParent(this); m_pworkUI->setWindowFlags(Qt::Dialog | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); m_pworkUI->setWindowIcon(QIcon(":/image/leaper")); m_pworkUI->setWindowModality(Qt::ApplicationModal); m_pworkUI->setAttribute(Qt::WA_ShowModal, true); m_pworkUI->onExec(); } } else if ("action_algParam" == strObj)//算法参数设置 { if (m_pAlgParamDlg) { m_pAlgParamDlg->setParent(this); m_pAlgParamDlg->setWindowTitle(tr("算法参数")); m_pAlgParamDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_pAlgParamDlg->setWindowIcon(QIcon(":/image/leaper")); //m_pAlgParamDlg->setWindowModality(Qt::ApplicationModal); //m_pAlgParamDlg->setAttribute(Qt::WA_ShowModal, true); m_pAlgParamDlg->show(); } } else if ("action_checkdata" == strObj) {//历史数据查询 QProcess process; process.setWorkingDirectory(QCoreApplication::applicationDirPath()); #ifdef _DEBUG QString strTaskName = "lpReportd.exe"; #else QString strTaskName = "lpReport.exe"; #endif process.startDetached(strTaskName); } else if ("action_modelmgr" == strObj) {//模板管理 if (DetectState::instance()->IsDetect) { //正在检测 不能使用模板管理功能 QMessageBox infobox(QMessageBox::Information, tr("提示"), tr("请停止检测再使用该功能."), QMessageBox::Yes, this); infobox.setWindowIcon(QIcon(":/image/leaper")); infobox.setButtonText(QMessageBox::Yes, tr("确认")); infobox.exec(); onStrongButton(); return; } if (m_pModelMgrDlg) { m_pModelMgrDlg->setParent(this); m_pModelMgrDlg->setWindowTitle(tr("模板管理")); m_pModelMgrDlg->setWindowFlags(Qt::Dialog | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); m_pModelMgrDlg->setWindowIcon(QIcon(":/image/leaper")); m_pModelMgrDlg->setWindowModality(Qt::ApplicationModal); m_pModelMgrDlg->setAttribute(Qt::WA_ShowModal, true); m_pModelMgrDlg->show(); } } else if ("actionSystemSeting" == strObj) {//系统参数设置 if (m_pSystemSettingDlg) { m_pSystemSettingDlg->setParent(this); m_pSystemSettingDlg->onShowWidget(lpGlobalData::instance()->m_level); m_pSystemSettingDlg->setWindowTitle(tr("系统参数设置")); m_pSystemSettingDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_pSystemSettingDlg->setWindowIcon(QIcon(":/image/leaper")); m_pSystemSettingDlg->setWindowModality(Qt::ApplicationModal); m_pSystemSettingDlg->setAttribute(Qt::WA_ShowModal, true); m_pSystemSettingDlg->show(); } } else if ("actioncamSetting" == strObj) { if (m_CamSettingDlg) { m_CamSettingDlg->setParent(this); //m_CamSettingDlg->onShowWidget(lpGlobalData::instance()->m_level); m_CamSettingDlg->setWindowTitle(tr("相机配置")); m_CamSettingDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_CamSettingDlg->setWindowIcon(QIcon(":/image/leaper")); m_CamSettingDlg->setWindowModality(Qt::ApplicationModal); m_CamSettingDlg->setAttribute(Qt::WA_ShowModal, true); m_CamSettingDlg->onInitWidget(); m_CamSettingDlg->show(); } } else if ("action_register" == strObj) { if (m_pCheckLineseUI) { m_pCheckLineseUI->setInfo(lpCheckKey::instance()->getSerialNo(), lpGlobalData::instance()->m_bCheckLinese); m_pCheckLineseUI->setParent(this); m_pCheckLineseUI->setWindowTitle(tr("注册")); m_pCheckLineseUI->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); m_pCheckLineseUI->setWindowIcon(QIcon(":/image/leaper")); m_pCheckLineseUI->setWindowModality(Qt::ApplicationModal); m_pCheckLineseUI->setAttribute(Qt::WA_ShowModal, true); m_pCheckLineseUI->show(); } } } Q_SLOT void lpMainWin::onButtonClicked() { QString strObj = sender()->objectName(); if ("btn_start_detect" == strObj)//开始 { //开始检测按钮 if (DetectState::instance()->IsDetect == false) { ui.btn_start_detect->setText(tr("停止检测")); m_pCtrl->onStart(); QString str = tr("按下了开始检测按钮,检测功能开启"); m_pCtrl->addLog(str, emTypeRunState); //DetectState::instance()->bLockDetect = true; } else { m_pCtrl->onFinish(); ui.btn_start_detect->setText(tr("开始检测")); QString str = tr("按下了停止检测按钮,检测功能关闭"); m_pCtrl->addLog(str, emTypeRunState); //DetectState::instance()->bLockDetect = false; } DetectState::instance()->IsDetect = !DetectState::instance()->IsDetect; } else if ("btn_clear_data" == strObj) {//交班清零 QMessageBox infobox(QMessageBox::Warning, tr("提示"), tr("将清空所有数据"), QMessageBox::Yes | QMessageBox::Cancel, this); infobox.setButtonText(QMessageBox::Yes, tr("确定")); infobox.setButtonText(QMessageBox::Cancel, tr("取消")); infobox.setWindowIcon(QIcon(":/image/leaper")); if (QMessageBox::Cancel != infobox.exec()) { m_pCtrl->onClear(); ui.main_lb_res_ok_num->setText(QString::number(0)); ui.main_lb_res_ng_num->setText(QString::number(0)); QString str = m_pCtrl->getUserName() + ":" + tr("按下了清零按钮,数据全部清零"); m_pCtrl->addLog(str, emTypeUseState); } } } QString lpMainWin::SecondTimeString(quint64 value) { QString strTime; int seconds = value % 60; int minutes = value / 60; QString strDay = tr("天"); QString strHour = tr("时"); QString strMinute = tr("分"); QString strSecond = tr("秒"); strTime = QString("%1%2%3%4").arg(minutes).arg(strMinute).arg(seconds).arg(strSecond); if (minutes >= 60) { minutes = (value / 60) % 60; int hours = (value / 60) / 60; strTime = QString("%1%2%3%4%5%6").arg(hours).arg(strHour).arg(minutes).arg(strMinute).arg(seconds).arg(strSecond); if (hours >= 24) { hours = ((value / 60) / 60) % 24; int day = ((value / 60) / 60) / 24; strTime = QString("%1%2%3%4%5%6%7%8").arg(day).arg(strDay).arg(hours).arg(strHour).arg(minutes).arg(strMinute).arg(seconds).arg(strSecond); } } return strTime; } void lpMainWin::timerEvent(QTimerEvent *event) { if (event->timerId() == m_timerID) { //定时刷新系统信息 m_runTimeCount++; if (m_pLbCurrentTime) { QString m_currentTime = hubBase::genDateTime(); QString strlong = SecondTimeString(m_runTimeCount); QString strTimeTitle = tr("运行时长:"); QString strShow = QString("%1 %2 %3").arg(m_currentTime).arg(strTimeTitle).arg(strlong); m_pLbCurrentTime->setText(strShow); m_pLbCurrentTime->setStyleSheet("font: 14px;"); } // state if (m_pLbDetectState) { QString strDetectState = DetectState::instance()->IsDetect == true ? tr("检测中...") : tr("未检测..."); m_pLbDetectState->setText(strDetectState); if (DetectState::instance()->IsDetect) { m_pLbDetectState->setStyleSheet("font: bold 14px;background-color: green;"); } else { m_pLbDetectState->setStyleSheet("font: bold 14px;background-color: red;"); } } if (m_pLbBanci) { QString show_label; if (m_pCtrl) show_label = m_pCtrl->getCurrentBan(); QString strMsg = tr("班次信息:") + (show_label.isEmpty() == true ? tr("该时间段未设置班次") : show_label); m_pLbBanci->setText(strMsg); m_pLbBanci->setStyleSheet("font: 14px;"); } if (m_pLbUser) { QString show_label = m_pCtrl->getUserName(); m_pLbUser->setText(tr("当前用户:") + show_label); m_pLbUser->setStyleSheet("font: 14px;"); } if (m_pLbPLCConnect) { if (lpGlobalData::instance()->m_plcConnect == true) { m_pLbPLCConnect->setText(tr("PLC已连接")); m_pLbPLCConnect->setStyleSheet("font: bold 14px;background-color: green;"); } else { m_pLbPLCConnect->setText(tr("PLC未连接")); m_pLbPLCConnect->setStyleSheet("font: bold 14px;background-color: red;"); } } } else if (event->timerId() == m_timerID_btn) { ui.btn_start_detect->setStyleSheet(""); killTimer(m_timerID_btn); m_timerID_btn = 0; } else if(m_timerID_Init == event->timerId()) { killTimer(m_timerID_Init); m_timerID_Init = 0; //打开开始检测按钮 ui.btn_start_detect->setText(tr("停止检测")); DetectState::instance()->IsDetect = true; m_pCtrl->onStart(); } } void lpMainWin::closeEvent(QCloseEvent *event) { QMessageBox info(this); info.setWindowIcon(QIcon(":/image/leaper")); info.setWindowTitle(QObject::tr("警告")); info.setText(QObject::tr("本检测系统正在运行,您真的要关闭?")); info.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); info.setButtonText(QMessageBox::Ok, QObject::tr("确定")); info.setButtonText(QMessageBox::Cancel, QObject::tr("取消")); if (info.exec() != QMessageBox::Ok) { return event->ignore(); } if (m_pDebugDlg) { if (!m_pDebugDlg->isHidden()) { m_pDebugDlg->close(); } } return event->accept(); } void lpMainWin::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) { ui.retranslateUi(this); } } void lpMainWin::SendModelKuTskFun() { /* 发送模板库线程 把已有的所有模板库全部发送至PLC中 */ DetectState::instance()->m_ThreadWaitTime = 100; const int c_nErrorTime = 3; int nError = 0; QMap*ptr = m_pCtrl->getAllModelMapPtr(); QList lst = ptr->keys(); if (ptr->size() > 0 && lst.size() > 0) { int nIndex = 0; do { IWheelModel *p = ptr->value(lst.at(nIndex)); emit sgTaskSendModels(nIndex + 1, lst.at(nIndex), p->getDiameter(), p->getThickness()); bool b = this->SendModelLibTask->WaitForSingle(DetectState::instance()->m_ThreadWaitTime); if (!b) { nError++; if (DetectState::instance()->m_PLC_ASK == 1) { if (nError > c_nErrorTime) { ++nIndex; nError = 0; qDebug() << "timeout, more than 3 times, cannot rev ask"; } } else { ++nIndex; nError = 0; } } else { nError = 0; nIndex++; } } while (nIndex < lst.size()); } emit(sgShowMsgdlg(tr("模板库发送完成"))); } void lpMainWin::SendTickTskFun() { //心跳包发送 if (m_pNet) { m_pNet->sendPulse(6000, DetectState::instance()->IsDetect, DetectState::instance()->IsOnline); //m_TimerID = startTimer(500); } } void lpMainWin::onSetModel() { /* 重新加载模板 重新设置模板到算法中使用 */ forDefectList = pWorkCtrl->getDefectList(); if (m_pTableCheck) { QStringList strList = forDefectList; if (!strList.contains("NG")) strList.append("NG"); m_pTableCheck->setModelList(strList); } QString str = QString("%1:%2(%3)").arg(tr("正在检测型号数")).arg(forDefectList.size()).arg(m_pCtrl->getAllTrainModelName().size() - 1); ui.main_showWorkLabel->setText(str); // IWheelUi *pMainWidget = m_pUi->getItemWidget(WHEEL_UI_MAINWINDOW); // if (pMainWidget) { // pMainWidget->setViewList(forDefectList); // } // void* address = (void*)m_pCtrl->getAllModelMapPtr(); // gpTpCoreCtrl->ISetAlgorithmShared("modelMap", (int)address); // QVariant filepath = QVariant(QCoreApplication::applicationDirPath()); // gpTpCoreCtrl->ISetAlgorithmShared("filepath", filepath); // // void* pdefectList = (void*)&forDefectList; // gpTpCoreCtrl->ISetAlgorithmShared("defectList", (int)pdefectList); } ///******************************************************************************* Q_SLOT void lpMainWin::onUpdateDefect() { forDefectList = pWorkCtrl->getDefectList(); if (m_pTableCheck) { QStringList strList = forDefectList; if (!strList.contains("NG")) strList.append("NG"); m_pTableCheck->setModelList(strList); } QString str = QString("%1:%2(%3)").arg(tr("正在检测型号数")).arg(forDefectList.size()).arg(m_pCtrl->getAllTrainModelName().size() - 1); ui.main_showWorkLabel->setText(str); } Q_SLOT void lpMainWin::onTcpConnet(QString str, bool bConnect) { static bool nTcpConnetSetting = true; QTextBrowser *m_Tcp_textbrower = ui.main_textBrowser; if (m_Tcp_textbrower && nTcpConnetSetting == true) { m_Tcp_textbrower->clear(); QTextDocument *pDoc = m_Tcp_textbrower->document(); pDoc->setMaximumBlockCount(10244); nTcpConnetSetting = false; } if (m_Tcp_textbrower) { if (!bConnect) { QColor m_color(255, 0, 0); m_Tcp_textbrower->setTextColor(m_color); } else { QColor m_color(16, 67, 24); m_Tcp_textbrower->setTextColor(m_color); } m_Tcp_textbrower->append(str); QTextCursor cursor = m_Tcp_textbrower->textCursor(); cursor.movePosition(QTextCursor::End); m_Tcp_textbrower->setTextCursor(cursor); } } Q_SLOT void lpMainWin::onSendClearLib2PLC() { if (m_pNet) m_pNet->sendClearLib(); } Q_SLOT void lpMainWin::onClientConnect(QString addr, bool bConnect) { /*判断连接的机器IP地址是不是本地设置好的IP,并检测他的连接状态,如果是 默认将发送模板库给他*/ QString m_addr = NetProtocol::genAddressPort(m_pNet->getIp(emNetClient), m_pNet->getPort(emNetClient)); if (m_addr == addr && bConnect) { QTimer::singleShot(200, this, SLOT(onSendClearLib2PLC())); } if (bConnect == true && 1 == DetectState::instance()->IsOnline) { //m_pUi->onSwitchOnlineModel(m_pState->IsOnline);//在线模式 离线模式切换 } QString strMsg; if (bConnect) { strMsg += QString("IP:%1 %2").arg(addr).arg(tr("已连接")); } else { strMsg += QString("IP:%1 %2").arg(addr).arg(tr("已断开")); } m_pCtrl->addLog(strMsg, emTypeRunState); ui.main_textBrowser->append(strMsg); } Q_SLOT void lpMainWin::onThickness(double dValue) { m_pCtrl->appendThicknessValue(dValue); } Q_SLOT void lpMainWin::onDetectStateRecv(int nIndex, int value) { nIndex -= 1; QMap *ptr = m_pCtrl->getAllModelMapPtr(); if (ptr) { QList lst = ptr->keys(); if (nIndex < lst.size() && nIndex >= 0) { IWheelModel*pModel = ptr->value(lst.at(nIndex)); pModel->setDetectState(value); emit(m_pCtrl->sgModelChanged(lst.at(nIndex))); } else { qDebug() << "rev detect state, index big than lst size"; } } } Q_SLOT void lpMainWin::onClearLibRev(bool state) { /*接收到库清空应答*/ if (SendModelLibTask) { if (SendModelLibTask->isRunning()) SendModelLibTask->stop(); if (m_pNet) m_pNet->sendModelNum(m_pCtrl->getAllModelMapPtr()->size()); SendModelLibTask->start(); } } //接收到心跳包 关闭定时器 Q_SLOT void lpMainWin::onPulseRev() { if (m_TimerID != 0) { killTimer(m_TimerID); m_TimerOutCount = 0; m_RestartServerCount = 0; } } Q_SLOT void lpMainWin::onRecvTrigPara() { emit(sgShowMsgdlg(tr("PLC已收到相关设置参数!"))); } Q_SLOT void lpMainWin::onReadDetectState(int nIndex, QString strModel) { nIndex -= 1; QMap *ptr = m_pCtrl->getAllModelMapPtr(); if (ptr) { QList lst = ptr->keys(); /*if (nIndex < lst.size() && nIndex >= 0)*/ { IWheelModel*pModel = ptr->value(strModel); if (pModel) { pModel->setDetectState(1); emit(m_pCtrl->sgModelChanged(strModel)); } } } } Q_SLOT void lpMainWin::onReadDetectStateASK() { QMap *ptr = m_pCtrl->getAllModelMapPtr(); if (ptr) { QList lst = ptr->keys(); for (int nIndex = 0; nIndex < lst.size(); nIndex++) { IWheelModel*pModel = ptr->value(lst.at(nIndex)); pModel->setDetectState(0); emit(m_pCtrl->sgModelChanged(lst.at(nIndex))); } } } Q_SLOT void lpMainWin::onTrigRecv(int m_value,double dRatio) { m_glbalRatio = dRatio; /*用于接收PLC触发相机的信号 自检是否收到图像 */ qDebug() << "recv a camera trig :" << QString::number(m_value); qWarning() << "recv a Triger signal from PLC:" << "(" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz") << ")"; //if (m_pState)//如果是使用软件触发相机拍照 { //if (DetectState::instance()->m_CameraTrigeType == 0)//软件触发模式 { if (DetectState::instance()->IsDetect == true) { // if (m_exposureTimeCount != 0) // { // m_pCoreCtrl->ISetExposureTime(m_camKey, m_exposureTimeArray[m_exposureTimeCount]); // } onTriggerCam(); qWarning() << "soft ctrol camera :" << "(" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz") << ")"; } } } } Q_SLOT void lpMainWin::onServerState(QString Addr, int port, bool m_state) { QString str; if (m_state == true) str = QString(tr("已打开")); else str = QString(tr("已关闭")); QString strMsg = QString("serverIP %1 port %2 %3.").arg(Addr).arg(port).arg(str); m_pCtrl->addLog(m_pCtrl->getUserName() + ":" + strMsg, emTypeRunState); } Q_SLOT void lpMainWin::onShutDownComputer() { qApp->closeAllWindows(); HANDLE hToken; TOKEN_PRIVILEGES tkp; OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&osvi) == 0) return; if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { // Windows NT 3.51, Windows NT 4.0, Windows 2000, // Windows XP, Windows .NET Server if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return; LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL); } ExitWindowsEx(EWX_SHUTDOWN, SHTDN_REASON_MAJOR_OTHER); } //*********************************************************************** Q_SLOT void lpMainWin::onPulseTimer() { //心跳包发送 if (m_pNet) { m_pNet->sendPulse(6000, DetectState::instance()->IsDetect, DetectState::instance()->IsOnline); //m_TimerID = startTimer(500); } } Q_SLOT void lpMainWin::onTaskSendModels(int nIndex, QString strModel, double dDiameter, double dHeight) { if (m_pNet) m_pNet->sendModelList(nIndex, strModel, dDiameter, dHeight); } Q_SLOT void lpMainWin::onTaskSendDetectState(int nIndex, QString strModel, int IsState) { if (m_pNet) m_pNet->sendDeteStateList(nIndex, IsState, strModel); } Q_SLOT void lpMainWin::onTaskCheck(int nIndex, int IsState, QString strModel) { if (m_pNet) m_pNet->sendCheckDeteStateList(nIndex, IsState, strModel); } Q_SLOT void lpMainWin::onShowImgState(QString str) { ui.main_label_state->setText(str); } Q_SLOT void lpMainWin::onGetImg() { ui.main_lb_res_model_pic->setStyleSheet(QString("QLabel{border: 1px solid rgb(0,0,0,250);background-color: rgb(200, 200, 200);}")); } //展示信息 Q_SLOT void lpMainWin::onShowMsg(QString str) { QPulpewidget *pw = new QPulpewidget(); pw->setParent(this); pw->showmessage(str); connect(pw, SIGNAL(finished()), pw, SLOT(deleteLater())); connect(pw, SIGNAL(finished()), this, SLOT(onInitPW())); } Q_SLOT void lpMainWin::onSendDisLib(int nIndex, QString strModel) { m_pNet->sendDisLibs(nIndex, strModel); } Q_SLOT void lpMainWin::onSendDisLibDone() { m_pNet->sendDisLibsDone(); } Q_SLOT void lpMainWin::onShowChannel(QString str) { ui.main_lb_res_Channle_Show->setText(str); } Q_SLOT void lpMainWin::onTriggerCam() { if (m_pCoreCtrl) { QStringList strLst = m_pCoreCtrl->ICameraKeys(); m_pCoreCtrl->ISnapImage(strLst); } } Q_SLOT void lpMainWin::onChangePLCParam() { if(m_pNet) m_pNet->sendTrigerPara(DetectState::instance()->m_PLC_TrigerFilter, DetectState::instance()->m_PLC_CamTrigDelay, DetectState::instance()->m_PLC_CamTrigPulse, DetectState::instance()->m_PLC_LightDelay, DetectState::instance()->m_PLC_TrigerType, DetectState::instance()->m_PLC_ResHoldTime); } void lpMainWin::onInitAbout() { QString aboutString; aboutString = QString( "

%1

" "

%2.

" "

%3:www.hzleaper.com

" "

%4:%5

" "

%6:%7

" "

%8:%9

" "

%10

" ).arg(tr("轮毂型号识别系统")) .arg(tr("本软件由杭州利珀科技开发,用于轮毂型号识别和分类,可搭配流水线运输系统使用")) .arg(tr("若需要进一步了解该产品的相关信息,请访问我们的网站")) .arg(tr("软件版本")).arg(VERSION_HUB) .arg(tr("算法版本")).arg(VERSION_ALG) .arg(tr("最后更新时间")).arg(UPDATE_TIME) .arg(tr("版权 (c) 属 杭州利珀科技有限公司 所有")); m_aboutDlg.setFixedSize(500, 300); QTextEdit* pEdit = new QTextEdit(&m_aboutDlg); pEdit->setReadOnly(true); pEdit->append(aboutString); pEdit->setAttribute(Qt::WA_TranslucentBackground, true); QPalette pl = pEdit->palette(); pl.setBrush(QPalette::Base, QBrush(QColor(255, 0, 0, 0))); pEdit->setPalette(pl); QPushButton* lbClose = new QPushButton(tr("关闭")); QGridLayout* lbLayout = new QGridLayout(&m_aboutDlg); lbLayout->addWidget(pEdit, 2, 1, 1, 3); lbLayout->addWidget(lbClose, 3, 2); lbClose->setMaximumSize(QSize(100, 50)); connect(lbClose, SIGNAL(clicked()), &m_aboutDlg, SLOT(hide())); } Q_SLOT void lpMainWin::onLanguageChange(QString strLanguage) { QSettings languageSetting("hubdetect.ini", QSettings::IniFormat); languageSetting.setValue("language", strLanguage); SetLanguage(strLanguage); } void lpMainWin::onShowResult(Result2Ui* pRlt) { if (!pRlt) return; /* ui.main_lb_res_model_pic;//匹配结果图 ui.main_lb_res_okng;//匹配结果 OK NG ui.main_lb_res_model_id;//匹配型号 ui.main_lb_res_model_score;//匹配分数 ui.main_lb_res_model_thickness;//厚度 ui.main_lb_res_model_diameter;//直径 ui.main_lb_res_model_time;//识别耗时时间 ui.main_lb_res_ok_num;//识别总数 ui.main_lb_res_ng_num;//NG 数量 */ int scareh = ui.main_lb_res_model_pic->height(); int scarew = ui.main_lb_res_model_pic->width(); int scare = 0; if (scareh > scarew) scare = scarew; else scare = scareh; if (pRlt->m_strModel.isEmpty()) { DetectState::instance()->totalUnDetectNum++; QPixmap pix(":/image/none.jpg"); ui.main_lb_res_model_pic->setPixmap(pix.scaled(scare - 15, scare - 15)); ui.main_lb_res_model_pic->setStyleSheet(QString("QLabel{border: 5px solid rgb(250,0,0,250);background-color: rgb(200, 200, 200);}")); pRlt->m_strModel = "NG"; ui.main_lb_res_okng->setText("NG"); ui.main_lb_res_okng->setStyleSheet("font: 75 24pt \"Consolas\";background-color: rgb(255, 0, 0);"); IWheelModel *pModel = m_pCtrl->getModel("NG"); if (pModel) { pModel->increCount(); emit m_pTableCheck->sgValueChange(pModel->getModelID()); } } else { IWheelModel *pModel = m_pCtrl->getModel(pRlt->m_strModel); if (pModel) { QString filepath = m_pCtrl->appRoot() + pModel->getPicPath(); QPixmap pix(filepath); ui.main_lb_res_model_pic->setPixmap(pix.scaled(scare - 15, scare - 15)); pModel->increCount(); ui.main_lb_res_okng->setText("OK"); ui.main_lb_res_okng->setStyleSheet("font: 75 24pt \"Consolas\";background-color: rgb(0, 255, 0);"); ui.main_lb_res_model_pic->setStyleSheet(QString("QLabel{border: 5px solid rgb(0,250,0,250);background-color: rgb(200, 200, 200);}")); emit m_pTableCheck->sgValueChange(pModel->getModelID()); } } DetectState::instance()->totalDetectNum++; //show ui.main_lb_res_ng_num->setText(QString::number(DetectState::instance()->totalUnDetectNum)); ui.main_lb_res_ok_num->setText(QString::number(DetectState::instance()->totalDetectNum)); ui.main_lb_res_model_time->setText(QString::number(pRlt->m_dRunTime, 'f', 2)); ui.main_lb_res_model_thickness->setText(QString::number((int)pRlt->m_dThickness)); ui.main_lb_res_model_diameter->setText(QString::number((int)pRlt->m_dDiameter)); ui.main_lb_res_model_id->setText(pRlt->m_strModel); ui.main_lb_res_model_score->setText(QString::number(pRlt->m_dScore * 100, 'f', 1) + "%"); if (m_pixMapList) { if (pRlt->m_pixResult.isNull()) m_pixMapList->addItemByLimit(pRlt->m_pixSrc, pRlt->m_strModel); else m_pixMapList->addItemByLimit(pRlt->m_pixResult, pRlt->m_strModel); } } void lpMainWin::SendResultBee(emTypeBee m_Type, int num) { //qDebug() << "sendResultBeeLight"; //SComframe frame; //if (m_Type == LIGHT_REDBEE) { // frame.data1 = 1; // frame.data2 = num; // SendDataToCom(0x46, frame); //} //else if (m_Type == LIGHT_GREENBEE) { // frame.data1 = 2; // frame.data2 = 0; // frame.data3 = num; // SendDataToCom(0x46, frame); //} //else if (m_Type == LIGHT_YELLOWBEE) { // frame.data1 = 4; // frame.data2 = 0; // frame.data3 = 0; // frame.data4 = num; // SendDataToCom(0x46, frame); //} //else if (m_Type == LIGHT_BEE) { // frame.data1 = 8; // frame.data2 = 0; // frame.data3 = 0; // frame.data4 = 0; // frame.data5 = num; // SendDataToCom(0x46, frame); //} if (m_Type == LIGHT_REDBEE) { m_pNet->sendLight(0, 1, 500, 500);//红灯 } else if (m_Type == LIGHT_GREENBEE) { m_pNet->sendLight(2, 1, 500, 500); } else if (m_Type == LIGHT_YELLOWBEE) { m_pNet->sendLight(1, 1, 500, 500); } else if (m_Type == LIGHT_BEE) { m_pNet->sendLight(3, 1, 500, 500); } } void lpMainWin::SendResultStr2PLC(Result2Ui* m_Res) { qDebug() << "sendResultToPLC resultName=" << m_Res->m_strModel << endl; if (m_pNet) m_pNet->sendDetectResult(m_Res->m_strModel, m_Res->m_dDiameter, m_Res->m_dThickness); } void lpMainWin::SendResultChannel2PLC(Result2Ui* m_Res) { qDebug() << "SendResultChannel2PLC"; CChannelInfo *pChannelInfo = m_pCtrl->getChannelInfo(); ChannelInfo *npInfo = pChannelInfo->getChannelInfo(m_Res->m_strModel); if (npInfo && DetectState::instance()->m_bObjAll2A == false) { if (m_pNet) m_pNet->sendResultChannel(npInfo->m_value, m_Res->m_dDiameter, m_Res->m_dThickness, m_Res->m_strModel); emit(sgShowChannelRes(npInfo->m_ChannelName)); } else { int defaultChannel = pChannelInfo->getDefaultChannel(); ChannelInfo *defaultInfo = pChannelInfo->getChannelInfo(defaultChannel); int nResultChannel = 0; if (defaultInfo) { nResultChannel = defaultInfo->m_value; emit(sgShowChannelRes(defaultInfo->m_ChannelName + tr("(默认)"))); } else { nResultChannel = 1000; emit(sgShowChannelRes(tr("默认通道 值1000"))); } if (m_pNet) m_pNet->sendResultChannel(nResultChannel, m_Res->m_dDiameter, m_Res->m_dThickness, m_Res->m_strModel); } } void lpMainWin::SendResultChannelCOM(Result2Ui* m_Res) { qDebug() << "SendResultStr2COM"; if (!m_pCtrl) return; CChannelInfo *pChannelInfo = m_pCtrl->getChannelInfo(); ChannelInfo *npInfo = pChannelInfo->getChannelInfo(m_Res->m_strModel); //SComframe frame; //if (npInfo&&m_pState->m_bObjAll2A == false) { // frame.data1 = npInfo->m_value; // SendDataToCom(0x47, frame); // emit(sgShowChannelRes(npInfo->m_ChannelName)); //} //else //{ // int defaultChannel = pChannelInfo->getDefaultChannel(); // ChannelInfo *defaultInfo = pChannelInfo->getChannelInfo(defaultChannel); // if (defaultInfo) // { // frame.data1 = defaultInfo->m_value; // emit(sgShowChannelRes(defaultInfo->m_ChannelName + QString(tr("(默认)")))); // } // else // { // frame.data1 = 1000; // emit(sgShowChannelRes(tr("默认通道 值1000"))); // } // SendDataToCom(0x47, frame); //} } void lpMainWin::saveImage(Result2Ui* pRes) { if (pRes == nullptr) return; qDebug() << "satrt tread save Image"; QString curExposureTimeStr = QString::number(getCurExposureTime()); QDir testDir; bool IsTestDir = testDir.exists(DetectState::instance()->m_SaveImgDirPath); if (!IsTestDir) DetectState::instance()->m_SaveImgDirPath = DetectState::instance()->m_applicationDirPath; QString baseSavePath = DetectState::instance()->m_SaveImgDirPath + "\\Data\\"; QString dataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd"); QString fileSavePath = baseSavePath + "\\" + dataTime; QString filename = pRes->m_strModel; if (pRes->m_strModel != "NG") { QString goodsourceDir = fileSavePath + "\\Good"; filename += QString("_%1_%2_").arg((int)pRes->m_dThickness).arg((int)pRes->m_dDiameter); filename += QDateTime::currentDateTime().toString("hhmmsszzz"); if (DetectState::instance()->saveGood == 1) { goodsourceDir += "\\Source"; goodsourceDir += "\\"; goodsourceDir += pRes->m_strModel; QString resultpath = goodsourceDir + "\\" + filename + ".png"; saveImage(pRes->m_pixSrc, goodsourceDir + "\\", filename + ".png"); } QString goodtargetDir = fileSavePath + "\\Good"; if (DetectState::instance()->saveCutGood == 1) { goodtargetDir += "\\Target"; goodtargetDir += "\\"; goodtargetDir += pRes->m_strModel; QString resultpath = goodtargetDir + "\\" + filename + "Res.png"; saveImage(pRes->m_pixResult, goodtargetDir + "\\", filename + "Res.png"); } } else { QString errorSourceDir = fileSavePath + "\\Error"; filename += QString("_%1_%2_").arg((int)pRes->m_dThickness).arg((int)pRes->m_dDiameter); filename += QDateTime::currentDateTime().toString("hhmmsszzz"); filename = filename + "_" + curExposureTimeStr; if (DetectState::instance()->saveBad == 1) { errorSourceDir += "\\Source"; QString resultpath = errorSourceDir + "\\" + filename + ".png"; saveImage(pRes->m_pixSrc, errorSourceDir + "\\", filename + ".png"); } QString errortargetDir = fileSavePath + "\\Error"; if (DetectState::instance()->saveCutBad == 1) { errortargetDir += "\\Target"; QString resultpath = errortargetDir + "\\" + filename + "Res.png"; if (pRes->m_pixResult.isNull()) saveImage(pRes->m_pixSrc, errortargetDir + "\\", filename + "Res.png"); else saveImage(pRes->m_pixResult, errortargetDir + "\\", filename + "Res.png"); } } } void lpMainWin::saveImage(const QPixmap& m_pixmap, QString m_path, QString filename) {//启动多线程保存图像 SaveImgThread *workTread = new SaveImgThread(this); workTread->setPixmap(m_pixmap, m_path, filename); connect(workTread, &SaveImgThread::finished, workTread, &QObject::deleteLater); workTread->start(); } void lpMainWin::onUpdateByLevel(int nlevel) { if(nlevel>4) ui.action_userManager->setVisible(true); else ui.action_userManager->setVisible(false); if (nlevel == 4) { ui.action_setting_ban->setDisabled(false); ui.actionSystemSeting->setDisabled(false); ui.action_algParam->setDisabled(false); ui.action_debug->setDisabled(false); } else if (nlevel > 4) { ui.action_cali_raster->setDisabled(false); ui.action_setting_ban->setDisabled(false); ui.action_setting_ip->setDisabled(false); ui.actioncamSetting->setDisabled(false); ui.actionSystemSeting->setDisabled(false); ui.action_algParam->setDisabled(false); ui.action_debug->setDisabled(false); } else { ui.action_cali_raster->setDisabled(true); ui.action_setting_ban->setDisabled(true); ui.action_setting_ip->setDisabled(true); ui.actioncamSetting->setDisabled(true); ui.actionSystemSeting->setDisabled(true); ui.action_algParam->setDisabled(true); ui.action_debug->setDisabled(true); } } Q_SLOT void lpMainWin::modWorkMgr(QString str) { m_pworkUI->modWorkMgr(str); } Q_SLOT void lpMainWin::onSendReadOnlineLib() { if (m_pNet) m_pNet->sendCheckAllModelState(); } Q_SLOT void lpMainWin::onThicknessTimer() { //查询厚度 if (m_pNet) m_pNet->sendThickness(); } Q_SLOT void lpMainWin::onwfPulseTimer() { // SComframe frame; // frame.data1 = 0; // frame.data2 = 0; // frame.data8 = 50; // SendDataToCom(0x43, frame); } Q_SLOT void lpMainWin::onUpdateExposureSetting() { QString strPath = QApplication::applicationDirPath(); readExposureTimeConfig(strPath); } bool lpMainWin::readExposureTimeConfig(const QString& strPath) { if(!m_exposureTimeArray.empty()) m_exposureTimeArray.clear(); QString filePath = strPath + "\\config\\exposure.json"; QJsonObject jsonObj = QZkJsonParser::ReadJsonAuto(filePath); if (jsonObj.empty()) { qDebug() << "Json file parsing failed!"; return false; } QJsonObject exposureObj = jsonObj.value("exposureTime").toObject(); QJsonObject::iterator objIterEnd = exposureObj.end(); for (auto objIter = exposureObj.begin(); objIter != objIterEnd; objIter++) { int exposureTime = objIter.value().toInt(); m_exposureTimeArray.emplace_back(exposureTime); } m_autoExposureSwitch = jsonObj.value("switch").toInt(); return true; } int lpMainWin::getCurExposureTime() { TP_CAMERA_OPTION camOpt; m_pCoreCtrl->IGetCameraOption(m_camKey, camOpt); return camOpt.exposure; } Q_SLOT void lpMainWin::onAutoExposure() { if (m_exposureTimeCount >= 0) { if (m_exposureTimeArray.size() <= m_exposureTimeCount) return; int exp = m_exposureTimeArray[m_exposureTimeCount]; qDebug() << "exp:" << exp; m_pCoreCtrl->ISetExposureTime(m_camKey, exp); } onTriggerCam(); } Q_SLOT void lpMainWin::onUpdateUI() { if (DetectState::instance()->m_IsUseChannel > 0) { ui.main_lb_res_Channle->setVisible(true); ui.main_lb_res_Channle_Show->setVisible(true); } else { ui.main_lb_res_Channle->setVisible(false); ui.main_lb_res_Channle_Show->setVisible(false); } if (DetectState::instance()->m_algParam.m_RatioDetectType > 0) { ui.label_ratioTitle->setVisible(true); ui.label_ratioValue->setVisible(true); } else { ui.label_ratioTitle->setVisible(false); ui.label_ratioValue->setVisible(false); } } Q_SLOT void lpMainWin::onShowRatioVal(double val) { ui.label_ratioValue->setText(QString("%1").arg(val)); } Q_SLOT void lpMainWin::onLineseCheck(bool bFlag) { ui.action_Login->setDisabled(!bFlag); ui.action_modelmgr->setDisabled(!bFlag); ui.action_checkdata->setDisabled(!bFlag); ui.action_connect_mode->setDisabled(!bFlag); if (m_pLabelInfo) { if (bFlag) { m_pLabelInfo->setText(tr("")); m_pLabelInfo->setStyleSheet(""); } else { m_pLabelInfo->setText(tr("本系统未注册激活")); m_pLabelInfo->setStyleSheet("font: bold 14px; color: red;"); } } } //强制刷新按钮提醒 void lpMainWin::onStrongButton() { if (m_timerID_btn == 0) { m_timerID_btn = startTimer(500); ui.btn_start_detect->setStyleSheet("font: bold 14px;background-color: rgb(210, 255, 44);"); } }