#include #include "lowesssmoother.h" #include "mainwindow.h" #include "ui_mainwindow.h" #include "global.h" #include "serialport.h" #include "dataparser.h" #include "filemanager.h" #include "logger.h" #include "xlsxhandler.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), _centralWidget(new CentralWidget(this)), _leftWidget(new LeftWidget(this)), _expertmentSettingForm(new ExperimentSettingForm(this)), _realTimeDataForm(new RealTimeDataForm(this)), _rightWidget(new QDockWidget(this)), _analysisSettingWidget(new AnalysisSettingForm(this)), _contextMenu(new QMenu(this)), _specificHeatComparisonMethodForm(new SpecificHeatComparisonMethodForm(this)), _instrumentCoefficientForm(new InstrumentCoefficientForm(this)), _degreeOfCureForm(new DegreeOfCureForm(this)), _OITAutoAnalysisParamForm(new OITAutoAnalysisParamForm(this)), _degreeOfCrystallinityForm(new DegreeOfCrystallinityForm(this)), _aboutForm(new AboutForm(this)), _enthalpyDataCorrectionForm(new EnthalpyDataCorrectionForm(this)), _coefficientSelectionForm(new CoefficientSelectionForm(this)), _printPreviewForm(new PrintPreviewForm(this)), _axisSettingForm(new AxisSettingForm(this)), _manuallyStopTheExperimentFlag(false) { ui->setupUi(this); ui->actionOITAutoAnalysisMode->setVisible(false); this->setToolTip("....."); ui->actionSaveas->setVisible(false); setCentralWidget(_centralWidget); addDockWidget(Qt::LeftDockWidgetArea, _leftWidget); addDockWidget(Qt::RightDockWidgetArea, _rightWidget); _rightWidget->setWidget(_analysisSettingWidget); _rightWidget->hide(); // ui->statusbar->showMessage("showMessage show temp message!"); // permenent show QLabel *permenentLabel = new QLabel(this); permenentLabel->setText("Software Ver:" + qApp->applicationVersion()); ui->statusbar->addPermanentWidget(permenentLabel); ui->actionTimeAxisAnalysisPCTMode->setCheckable(true); // setSubWidgetAttribute(_expertmentSettingForm); setSubWidgetAttribute(_specificHeatComparisonMethodForm); setSubWidgetAttribute(_realTimeDataForm); setSubWidgetAttribute(_degreeOfCureForm); setSubWidgetAttribute(_instrumentCoefficientForm); setSubWidgetAttribute(_OITAutoAnalysisParamForm); setSubWidgetAttribute(_degreeOfCrystallinityForm); setSubWidgetAttribute(_aboutForm); setSubWidgetAttribute(_enthalpyDataCorrectionForm); setSubWidgetAttribute(_coefficientSelectionForm); setSubWidgetAttribute(_printPreviewForm); setSubWidgetAttribute(_axisSettingForm); // setActionEnable(true); _eventHandler = _centralWidget->getEvnetHandler(); // connections(); // // ui->actionStop->setEnabled(false); } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotContextMenuShow(const QPoint point) { _contextMenu->exec(point); } void MainWindow::slotUpdateStatusbarMsg(const QString msg) { ui->statusbar->showMessage(msg); } void MainWindow::slotOITAutoAnalysis(const double x1, const double x2) { on_actionStop_triggered(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT); _centralWidget->setVerticalLineRange(x1, x2); } void MainWindow::slotStartExperiment() { startExperimentByDeviceInfo(); } void MainWindow::closeEvent(QCloseEvent *event) { // 弹出确认对话框 QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "确认退出", "你确定要退出吗?", QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { event->accept(); // 接受关闭事件,关闭窗口 } else { event->ignore(); // 忽略关闭事件,不关闭窗口 } } void MainWindow::connections() { // ui connect(_expertmentSettingForm, &ExperimentSettingForm::sigDeliverData, SerialPort::instance(), &SerialPort::slotDeliverData); #if 1 // SerialPort. connect(SerialPort::instance(), &SerialPort::sigSendCommonData, _centralWidget, &CentralWidget::slotRecvCommonData); connect(SerialPort::instance(), &SerialPort::sigSendCommonData, _realTimeDataForm, &RealTimeDataForm::slotRevCommonData); connect(SerialPort::instance(), &SerialPort::sigSendCommonDataToRealDataForm, _realTimeDataForm, &RealTimeDataForm::slotRevCommonData); connect(SerialPort::instance(), &SerialPort::sigSendPhaseInfo, _expertmentSettingForm, &ExperimentSettingForm::slotRecvPhaseInfo); connect(SerialPort::instance(), &SerialPort::sigAxisModify, _centralWidget, &CentralWidget::slotAxisModify); connect(SerialPort::instance(), &SerialPort::sigUpdateStatusbarMsg, this, &MainWindow::slotUpdateStatusbarMsg); connect(SerialPort::instance(), &SerialPort::sigSaveExperimentalDataMsgBox, this, &MainWindow::slotSaveExperimentalDataMsgBox); connect(SerialPort::instance(), &SerialPort::sigStartExperiment, this, &MainWindow::slotStartExperiment); #endif // mode // connect(Global::instance(), &Global::sigModeModify, // _centralWidget, &CentralWidget::slotModeModify); // analysis connect(_leftWidget, &LeftWidget::sigSendAnalysisFileName, _centralWidget, &CentralWidget::slotRecvAnalysisFileName); connect(_centralWidget, &CentralWidget::sigSendLineXCoord, _analysisSettingWidget, &AnalysisSettingForm::slotRecvLineXCoord); connect(_analysisSettingWidget, &AnalysisSettingForm::sigApply, _centralWidget, &CentralWidget::slotAnalysisSettingApply); connect(_analysisSettingWidget, &AnalysisSettingForm::sigUndo, _centralWidget, &CentralWidget::slotAnalysisSettingUndo); connect(_analysisSettingWidget, &AnalysisSettingForm::sigConfirm, _centralWidget, &CentralWidget::slotAnalysisSettingConfirm); connect(_analysisSettingWidget, &AnalysisSettingForm::sigCancel, _centralWidget, &CentralWidget::slotAnalysisSettingCancel); connect(_centralWidget, &CentralWidget::sigRightDockWidgetHide, [&]() { _rightWidget->hide(); }); connect(_degreeOfCrystallinityForm, &DegreeOfCrystallinityForm::sigDrawCustomText, _centralWidget, &CentralWidget::slotDrawCustomText); connect(_specificHeatComparisonMethodForm, &SpecificHeatComparisonMethodForm::sigDrawCustomText, _centralWidget, &CentralWidget::slotDrawCustomText); // SpecificHeatComparisonMethodForm connect(_eventHandler, &EventHandler::sigSetCurve, _specificHeatComparisonMethodForm, &SpecificHeatComparisonMethodForm::slotSetCurve); // Axis settings. connect(_axisSettingForm, &AxisSettingForm::sigGetAxisInfo, _centralWidget, &CentralWidget::slotGetAxisInfo); connect(_centralWidget, &CentralWidget::sigGetAxisInfoWithData, _axisSettingForm, &AxisSettingForm::slotGetAxisInfoWithData); connect(_axisSettingForm, &AxisSettingForm::sigSetAxisSettings, _centralWidget, &CentralWidget::slotSetAxisSettings); // OIT connect(OITAutoAnalysis::getInstance(), &OITAutoAnalysis::sigExperimentStop, this, &MainWindow::slotOITAutoAnalysis); } void MainWindow::setActionEnable(const bool flag) { if (flag) { ui->actionNew->setEnabled(true); ui->actionStart->setEnabled(true); ui->actionStop->setEnabled(true); ui->actionRealTimeWidget->setEnabled(true); } else { ui->actionNew->setEnabled(false); ui->actionStart->setEnabled(false); ui->actionStop->setEnabled(false); ui->actionRealTimeWidget->setEnabled(false); } } void MainWindow::setSubWidgetAttribute(QWidget *widget) { widget->setWindowModality(Qt::ApplicationModal); widget->setWindowFlags(Qt::Dialog); widget->setFixedSize(widget->geometry().width(), widget->geometry().height()); } #if 0 bool MainWindow::saveExperimentFile(const QString fileName) { QString localFileName = fileName; if(fileName.isEmpty()){ localFileName = "new"; } QString xlsxfilePath = Global::SampleDataFloder + "/" + localFileName + ".xlsx"; QString filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file", xlsxfilePath, "Excel Files (*.xlsx)"); logde<<"filePath:"<filePathCheck(fileName, folder); filePath = folder + "/" + localFileName + ".xlsx"; } else { QString xlsxfilePath = folder + "/" + localFileName + ".xlsx"; filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file", xlsxfilePath, "Excel Files (*.xlsx)"); } // finalFileName = localFileName + ".xlsx"; logde << "filePath:" << filePath.toStdString(); if (filePath.isEmpty()) { qDebug() << "User cancel the operation."; return false; } // Save file. if (mode == Global::Mode::Analysis) { if (Global::_curveFileDataVtr.empty()) { // 分析模式下,但是文件数据为空,说明做完实验没有保存数据。 XlsxHandler::writeExperimentFile(filePath); } else { // 分析模式下,存在文件数据,将文件数据写入文件。 XlsxHandler::writeXlsxFile(filePath); #if 0 // 分析模式下,直接保存从文件读取来的数据。 if(Global::_smoothnessFlag){ XlsxHandler::writeSmoothnessFile(filePath); }else{ // 直接在xlsx文件的基础上添加分析数据。 XlsxHandler::xlsxFileAppendAnalysisOperation(filePath); } #endif } } else if (mode == Global::Mode::Experiment) { XlsxHandler::writeExperimentFile(filePath); } return true; } void MainWindow::smoothness(const int level) { logde << "smoothness..."; slotUpdateStatusbarMsg("数据平滑计算中..."); if (!Global::_curveExperimentDataVtr.empty()) { // 当前数据为实验数据时,需要把所有的当前实验数据都进行平滑处理。 // 删除所有objectName为experiment的curve. _centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt); // 添加所有平滑后的curve. for (auto &item : Global::_curveExperimentDataVtr) { item.smoothDataVtr = smoothnessDetail(level, item.dataVtr); item.curve = _centralWidget->addCurveData(item.smoothDataVtr, Global::ObjectNameExperiemnt); } } else { // 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。 QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName(); _centralWidget->deleteCurveByObjectName(selectedCurveObjectName); for (Global::CurveFileData &cfd : Global::_curveFileDataVtr) { if (selectedCurveObjectName.contains(cfd.filePath)) { for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr) { pti.smoothDataVtr = smoothnessDetail(level, pti.dataVtr); pti.curve = _centralWidget->addCurveData(pti.smoothDataVtr, cfd.filePath); } } } } } QVector MainWindow::smoothnessDetail(const int level, const QVector &dataVtr) { Lowess::Config config; config.smoothingFactor = level * 0.01; config.robustnessIterations = 3; std::vector x; std::vector y; for (const Global::ExperimentData &ed : dataVtr) { if (Global::_axisMode == Global::AxisMode::SingleY) { x.push_back(ed.sampleTemp); } else { x.push_back(ed.runTime); } y.push_back(ed.dsc); } slotUpdateStatusbarMsg("数据平滑计算中..."); QVector resultVtr; logde << "smooth start..."; logde << "x,y size:" << x.size() << "," << y.size(); ui->statusbar->showMessage("数据平滑计算中..."); ui->statusbar->showMessage("数据平滑计算中..."); ui->statusbar->showMessage("数据平滑计算中..."); ui->statusbar->showMessage("数据平滑计算中..."); std::vector yest = Lowess::smooth(x, y, config); if (yest.empty()) { slotUpdateStatusbarMsg("数据平滑完成."); return resultVtr; } slotUpdateStatusbarMsg("数据平滑完成."); logde << "smooth end..."; // result data vector. for (int i = 0; i < x.size(); i++) { Global::ExperimentData ed; if (Global::_axisMode == Global::AxisMode::SingleY) { ed.sampleTemp = x.at(i); ed.runTime = dataVtr.at(i).runTime; } else { ed.runTime = x.at(i); ed.sampleTemp = dataVtr.at(i).sampleTemp; } ed.dsc = yest.at(i); ed.constantTempTime = dataVtr.at(i).constantTempTime; resultVtr.push_back(ed); } return resultVtr; } void MainWindow::smoothnessExperimentData(const int level) { #if 0 for(int i = 0;i < Global::_curveExperimentDataVtr.size();i++){ Global::CurveExperimentData ced = Global::_curveExperimentDataVtr.at(i); smoothnessDetail() } #endif for (auto &item : Global::_curveExperimentDataVtr) { smoothnessDetail(level, item.dataVtr); } } void MainWindow::startExperiment() { QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Start); QString hexData = ba.toHex(' '); SerialPort::instance()->slotSendData(ba); Global::_mode = Global::Mode::Experiment; _manuallyStopTheExperimentFlag = false; _centralWidget->startExperiment(); } void MainWindow::startExperimentByDeviceInfo() { Global::_mode = Global::Mode::Experiment; _manuallyStopTheExperimentFlag = false; _centralWidget->startExperiment(); // 实验开始,清除上一个实验所有数据。 Global::clearExperimentData(); } void MainWindow::on_actionStop_triggered() { logde << " Stop experiment ...++++++++++++++++++"; if (!SerialPort::instance()->isOpen()) { showMesgBox("设备未连接,请先连接设备。"); return; } if (Global::_mode == Global::Mode::Experiment) { QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Stop); SerialPort::instance()->slotSendData(ba); // Set software mode to analysis. _manuallyStopTheExperimentFlag = true; logde << "_manuallyStopTheExperimentFlag:" << _manuallyStopTheExperimentFlag; Global::_mode = Global::Mode::Analysis; // Save data. #if 1 logde << "on_actionStop_triggered saveFile ..."; QString finalFileName; if (saveFile(Global::_experimentInfo.sampleName, Global::Mode::Experiment, finalFileName, true)) { _leftWidget->reloadFileName(); QString str = QString("%1 文件保存成功。").arg(finalFileName); QMessageBox::information(this, "文件保存", str, QMessageBox::Yes); } #endif } } void MainWindow::on_actionNew_triggered() { if (!SerialPort::instance()->isOpen()) { showMesgBox("设备未连接,请先连接设备。"); return; } _expertmentSettingForm->show(); } void MainWindow::on_actionStart_triggered() { logde << "start experiment,set soft into experiment mode."; logde << "```````````````````````````````"; if (!SerialPort::instance()->isOpen()) { showMesgBox("设备未连接,请先连接设备。"); return; } on_actionClearAllData_triggered(); startExperiment(); } void MainWindow::on_actionReadOnly_triggered() { Global::_mode = Global::Mode::Experiment; SerialPort::instance()->openSp(); } void MainWindow::on_actionRealTimeWidget_triggered() { _realTimeDataForm->show(); } void MainWindow::slotSaveExperimentalDataMsgBox() { logde << "_manuallyStopTheExperimentFlag:" << _manuallyStopTheExperimentFlag; if (_manuallyStopTheExperimentFlag) { logde << "_manuallyStopTheExperimentFlag..."; return; } // auto save file. logde << "slotSaveExperimentalDataMsgBox saveFile ..."; QString finalFileName; if (saveFile(Global::_experimentInfo.sampleName, Global::Mode::Experiment, finalFileName, true)) { _leftWidget->reloadFileName(); QString str = QString("%1 文件保存成功。").arg(finalFileName); QMessageBox::information(this, "文件保存", str, QMessageBox::Yes); } #if 0 QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "数据保存提示", "是否保存实验数据?", QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { QString finaleFileName; saveFile(Global::_experimentInfo.sampleName,Global::Mode::Experiment,finaleFileName); _leftWidget->reloadFileName(); } else { on_actionClearAllData_triggered(); } #endif } void MainWindow::on_actionConnectToDev_triggered() { logde << "connect to device..."; if (SerialPort::instance()->isOpen()) { logde << "close device."; SerialPort::instance()->closeSp(); ui->actionConnectToDev->setIcon(QIcon(":/images/connect.png")); ui->actionConnectToDev->setText("连接设备"); logde << "close serial port."; // QString str("设备已断开。"); slotUpdateStatusbarMsg(str); showMesgBox(str); } else { logde << "open device."; if (SerialPort::instance()->openSp()) { setActionEnable(true); // Global::instance()->setMode(Global::Mode::ConnectedToDev); Global::_mode = Global::Mode::ConnectedToDev; QByteArray ba = DataParser::inquirePhaseInfo(); SerialPort::instance()->sendData(ba); ui->actionConnectToDev->setIcon(QIcon(":/images/disconnect.png")); ui->actionConnectToDev->setText("断开连接"); // QString str("设备已连接。"); slotUpdateStatusbarMsg(str); showMesgBox(str); logde << "open serial port success. "; } else { // QMessageBox::warning(this, "warnning", "Serial Port open failed."); showMesgBox("设备打开失败。"); } } } void MainWindow::on_actionStartPoint_triggered() { logde << "start experiment..."; _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StartPoint); } void MainWindow::on_actionStopPoint_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StopPoint); } void MainWindow::on_actionNumericalLabel_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::NumericalLabel); } void MainWindow::on_actionPeakSynthesisAnalysis_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::PeakSynthesisAnalysis); } void MainWindow::on_actionClearAllData_triggered() { // 实验过程中,不允许清除数据。 if(Global::_mode == Global::Mode::Experiment) { return; } slotUpdateStatusbarMsg(""); _rightWidget->hide(); _centralWidget->clearAllData(); } void MainWindow::on_actionGlassTransition_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::GlassTransition); } void MainWindow::on_actionOIT_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT); } void MainWindow::on_actionSpecificHeatCompMethod_triggered() { _specificHeatComparisonMethodForm->show(); } void MainWindow::on_actionDegreeOfCrystallinity_triggered() { // QMessageBox::warning(this, "warnning", "结晶度."); _degreeOfCrystallinityForm->show(); } void MainWindow::on_actionInstrumentParameter_triggered() { _instrumentCoefficientForm->show(); } void MainWindow::on_actionOITAutoAnalysisParam_triggered() { _OITAutoAnalysisParamForm->show(); } void MainWindow::on_actionOITAutoAnalysisMode_triggered() { } void MainWindow::on_actionTimeAxisAnalysisPCTMode_triggered() { Global::_displayTimeValue = ui->actionTimeAxisAnalysisPCTMode->isChecked(); } void MainWindow::on_actionDegreeOfCuring_triggered() { // _degreeOfCureForm->show(); } void MainWindow::on_actionAbout_triggered() { _aboutForm->show(); } void MainWindow::on_actionEnthalpyCorrectionEdit_triggered() { _enthalpyDataCorrectionForm->show(); } void MainWindow::on_actionEnthalpyCorrectionSelection_triggered() { _coefficientSelectionForm->show(); } void MainWindow::on_actionPrintPreview_triggered() { // _printPreviewForm->show(); _printPreviewForm->setPixmap(_centralWidget->getPixMap()); _printPreviewForm->_customPrintPreviewDialog->showMaximized(); } void MainWindow::on_actionOnsetTemperaturePoint_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OnsetTemperaturePoint); } void MainWindow::on_actionEndsetTemperaturePoint_triggered() { _rightWidget->show(); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::EndsetTemperaturePoint); } void MainWindow::on_actionYAxis_triggered() { _centralWidget->switchAxisMode(); } void MainWindow::on_actionAxisSetting_triggered() { _axisSettingForm->show(); } void MainWindow::on_actionSaveData_triggered() { QString finaleFileName; saveFile(Global::_experimentInfo.sampleName, Global::_mode, finaleFileName); _leftWidget->reloadFileName(); } void MainWindow::on_actionSaveas_triggered() { QString finaleFileName; saveFile(Global::_experimentInfo.sampleName, Global::Mode::None, finaleFileName); _leftWidget->reloadFileName(); } void MainWindow::on_actionLanguage_triggered() { if (Global::_languageType == Global::LanguageType::Chinese) { Global::_languageType = Global::LanguageType::English; ui->actionLanguage->setText(Global::EnglishStr); } else { Global::_languageType = Global::LanguageType::Chinese; ui->actionLanguage->setText(Global::ChineseStr); } } void MainWindow::on_actionSmoothness1_triggered() { smoothness(1); } void MainWindow::on_actionSmoothness2_triggered() { smoothness(2); } void MainWindow::on_actionSmoothness3_triggered() { smoothness(3); } void MainWindow::on_actionSmoothness4_triggered() { smoothness(4); } void MainWindow::on_actionSmoothness5_triggered() { smoothness(5); } void MainWindow::on_actionSmoothness6_triggered() { smoothness(6); } void MainWindow::on_actionSmoothness7_triggered() { smoothness(7); } void MainWindow::on_actionSmoothness8_triggered() { smoothness(8); } void MainWindow::on_actionSmoothness9_triggered() { smoothness(9); } void MainWindow::on_actionSmoothness10_triggered() { smoothness(10); } void MainWindow::on_actionOriginalData_triggered() { if (!Global::_curveExperimentDataVtr.empty()) { // 删除所有objectName为experiment的curve. _centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt); for (auto &item : Global::_curveExperimentDataVtr) { item.smoothDataVtr.clear(); item.curve = _centralWidget->addCurveData(item.dataVtr, Global::ObjectNameExperiemnt); } } else { // 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。 QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName(); _centralWidget->deleteCurveByObjectName(selectedCurveObjectName); for (Global::CurveFileData &cfd : Global::_curveFileDataVtr) { if (selectedCurveObjectName.contains(cfd.filePath)) { for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr) { pti.smoothDataVtr.clear(); pti.curve = _centralWidget->addCurveData(pti.dataVtr, cfd.filePath); } } } } #if 0 // process data. QVector targetDataVtr; QString objectName; QCPCurve ** curvePtrPtr; if(!Global::_curveExperimentDataVtr.empty()){ for(auto & item:Global::_curveExperimentDataVtr){ if(_centralWidget->isCurrentCurve(item.curve)){ targetDataVtr = item.dataVtr; objectName = Global::ObjectNameExperiemnt; curvePtrPtr = &item.curve; } } }else{ for(Global::CurveFileData &cfd :Global::_curveFileDataVtr){ for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){ if(_centralWidget->isCurrentCurve(pti.curve)){ targetDataVtr = pti.dataVtr; objectName = cfd.filePath; curvePtrPtr = &pti.curve; } } } } // _centralWidget->deleteCurveByObjectName(_centralWidget->getCurrentCurve()->objectName()); _centralWidget->addCurveData(targetDataVtr,objectName); *curvePtrPtr = _centralWidget->getCurrentCurve(); #endif } void MainWindow::showMesgBox(const QString str) { static bool isShow = false; if (!isShow) { isShow = true; QMessageBox::information(this, "提示", str); isShow = false; } }