From 36f05cb098710cb77a60bec62c41562d9a68d7e9 Mon Sep 17 00:00:00 2001 From: anxinglong <2910824064@qq.com> Date: Tue, 14 Jul 2026 17:56:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9ROI=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E6=97=B6=20=20=20=20=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=A4=9A=E6=9D=A1=20=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=95=88=E7=8E=87=E5=88=BB=E5=BA=A6=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TwoDSpectralCompliance.cpp | 26 ++- .../TwoDSpectralCompliance.h | 2 + .../AntiConformEnergySpectrumView.cpp | 22 ++- .../AntiConformEnergySpectrumView.h | 3 + .../ConformToTheEnergySpectrum.cpp | 20 ++- .../ConformToTheEnergySpectrum.h | 3 + .../CountRateAnalysisView.cpp | 25 ++- src/EfficiencyScale.ui | 162 ++++++++++-------- .../EnergyCountPeakFitView.cpp | 21 ++- .../EnergyCountPeakFitView.h | 3 + .../EnergyCountPlotView.cpp | 22 ++- src/EnergyCountPlotView/EnergyCountPlotView.h | 3 + src/EnergyScaleForm.cpp | 2 - src/MainWindow.cpp | 7 +- .../NuclideAnalysisView.cpp | 1 - src/analysisReport/reportwidget.cpp | 6 +- 16 files changed, 214 insertions(+), 114 deletions(-) diff --git a/src/2DSpectralCompliance/TwoDSpectralCompliance.cpp b/src/2DSpectralCompliance/TwoDSpectralCompliance.cpp index d95968e..0e8b0cd 100644 --- a/src/2DSpectralCompliance/TwoDSpectralCompliance.cpp +++ b/src/2DSpectralCompliance/TwoDSpectralCompliance.cpp @@ -31,7 +31,7 @@ #include #include "csv.h" #include - +//二维符合谱 class HeatMapColorMap : public QwtLinearColorMap { public: HeatMapColorMap() @@ -454,6 +454,17 @@ QwtPlotMarker *TwoDSpectralCompliance::createVLine(double x, Qt::GlobalColor col return marker; } +void TwoDSpectralCompliance::clearAllRoiMarkers() +{ + for (auto marker : _roiMarkers) + { + marker->detach(); // 从绘图面板解绑 + delete marker; // 销毁对象 + } + _roiMarkers.clear(); + _plot->replot(); // 刷新画布清除线条 +} + void TwoDSpectralCompliance::onSelection(const QRectF& rect) { // 忽略过小的选区(可能是误点击) @@ -494,21 +505,23 @@ void TwoDSpectralCompliance::onActionPlotConfigure() void TwoDSpectralCompliance::onActionRoiTriggered() { + clearAllRoiMarkers(); _roi->show(); } void TwoDSpectralCompliance::slot_roi_data(ROIItem &item) { + clearAllRoiMarkers(); // 第一组:起始1、结束1 红色竖线,必须存在才插入,所以一定绘制 - createVLine(item.s1, Qt::red, 1.2); - createVLine(item.e1, Qt::red, 1.2); + _roiMarkers.append(createVLine(item.s1, Qt::red, 1.2)); + _roiMarkers.append(createVLine(item.e1, Qt::red, 1.2)); // 第二组:起始2、结束2 有有效数值才绘制,无值跳过 bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0)); if (secondGroupValid) { - createVLine(item.s2, Qt::blue, 1.2); - createVLine(item.e2, Qt::blue, 1.2); + _roiMarkers.append(createVLine(item.s2, Qt::blue, 1.2)); + _roiMarkers.append(createVLine(item.e2, Qt::blue, 1.2)); } _plot->replot(); } @@ -550,7 +563,8 @@ void TwoDSpectralCompliance:: updateInfoContent() } } - if (totalPoints == 0) { + if (totalPoints == 0) + { m_totalEventsEdit->setText(QStringLiteral(u"0")); m_totalPointsEdit->setText(QStringLiteral(u"0")); m_maxCountEdit->setText(QStringLiteral(u"0")); diff --git a/src/2DSpectralCompliance/TwoDSpectralCompliance.h b/src/2DSpectralCompliance/TwoDSpectralCompliance.h index 504fdb4..a887e38 100644 --- a/src/2DSpectralCompliance/TwoDSpectralCompliance.h +++ b/src/2DSpectralCompliance/TwoDSpectralCompliance.h @@ -61,6 +61,7 @@ private: void updateToggleButtonPosition(); void updateShowButtonPosition(); QwtPlotMarker* createVLine(double x, Qt::GlobalColor color, double lineWidth = 1.0); // 创建垂直标记竖线 + void clearAllRoiMarkers(); // 清空所有ROI竖线标记 private slots: void showFloatingWidget(); @@ -112,6 +113,7 @@ private: double m_globalYMin = 0.0, m_globalYMax = 0.0; RegionOfInterest *_roi; + QList _roiMarkers; }; #endif // TWODSPECTRALCOMPLIANCE_H \ No newline at end of file diff --git a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp index 2f0ec01..fae034f 100644 --- a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp +++ b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp @@ -142,27 +142,41 @@ void AntiConformEnergySpectrumView::loadAndProcess() load_thread->start(); } +void AntiConformEnergySpectrumView::clearAllRoiMarkers() +{ + for (auto marker : _roiMarkers) + { + marker->detach(); // 从绘图面板解绑 + delete marker; // 销毁对象 + } + _roiMarkers.clear(); + _plot->replot(); // 刷新画布清除线条 +} + void AntiConformEnergySpectrumView::onActionPlotConfigure() { } void AntiConformEnergySpectrumView::onActionRoiTriggered() { + clearAllRoiMarkers(); _roi->show(); } void AntiConformEnergySpectrumView::slot_roi_data(ROIItem &item) { + clearAllRoiMarkers(); + // 第一组:起始1、结束1 红色竖线,必须存在才插入,所以一定绘制 - createVLine(item.s1, Qt::red, 1.2); - createVLine(item.e1, Qt::red, 1.2); + _roiMarkers.append(createVLine(item.s1, Qt::red, 1.2)); + _roiMarkers.append(createVLine(item.e1, Qt::red, 1.2)); // 第二组:起始2、结束2 有有效数值才绘制,无值跳过 bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0)); if (secondGroupValid) { - createVLine(item.s2, Qt::blue, 1.2); - createVLine(item.e2, Qt::blue, 1.2); + _roiMarkers.append(createVLine(item.s2, Qt::blue, 1.2)); + _roiMarkers.append(createVLine(item.e2, Qt::blue, 1.2)); } _plot->replot(); } diff --git a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h index 563f7f7..741e5a5 100644 --- a/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h +++ b/src/AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h @@ -24,6 +24,7 @@ protected: private: void setupMenu(); void loadAndProcess(); // 读取CSV,执行符合处理,绘制能谱折线图 + void clearAllRoiMarkers(); // 清空所有ROI竖线标记 private slots: void onActionPlotConfigure(); @@ -36,6 +37,8 @@ private: QwtPlotCurve* _curve = nullptr; QString _data_filename; RegionOfInterest *_roi; + QList _roiMarkers; + }; #endif // ANTICONFORMENERGYSPECTRUMVIEW_H diff --git a/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp b/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp index 0ab9604..a3481d8 100644 --- a/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp +++ b/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp @@ -181,6 +181,17 @@ void ConformToTheEnergySpectrum::loadAndProcess() load_thread->start(); } +void ConformToTheEnergySpectrum::clearAllRoiMarkers() +{ + for (auto marker : _roiMarkers) + { + marker->detach(); // 从绘图面板解绑 + delete marker; // 销毁对象 + } + _roiMarkers.clear(); + _plot->replot(); // 刷新画布清除线条 +} + void ConformToTheEnergySpectrum::onActionPlotConfigure() { @@ -189,21 +200,22 @@ void ConformToTheEnergySpectrum::onActionPlotConfigure() void ConformToTheEnergySpectrum::slot_roi_data(ROIItem &item) { // 第一组:起始1、结束1 红色竖线,必须存在才插入,所以一定绘制 - createVLine(item.s1, Qt::red, 1.2); - createVLine(item.e1, Qt::red, 1.2); + _roiMarkers.append(createVLine(item.s1, Qt::red, 1.2)); + _roiMarkers.append(createVLine(item.e1, Qt::red, 1.2)); // 第二组:起始2、结束2 有有效数值才绘制,无值跳过 bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0)); if (secondGroupValid) { - createVLine(item.s2, Qt::blue, 1.2); - createVLine(item.e2, Qt::blue, 1.2); + _roiMarkers.append(createVLine(item.s2, Qt::blue, 1.2)); + _roiMarkers.append(createVLine(item.e2, Qt::blue, 1.2)); } _plot->replot(); } void ConformToTheEnergySpectrum::onActionRoiTriggered() { + clearAllRoiMarkers(); _roi->show(); } diff --git a/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h b/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h index c9fbc16..8b775a4 100644 --- a/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h +++ b/src/ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h @@ -24,6 +24,7 @@ protected: private: void setupMenu(); void loadAndProcess(); // 读取CSV,执行符合处理,绘制能谱折线图 + void clearAllRoiMarkers(); // 清空所有ROI竖线标记 private slots: void onActionPlotConfigure(); @@ -37,6 +38,8 @@ private: QStringList _data_filenames; RegionOfInterest *_roi; + QList _roiMarkers; + }; #endif // CONFORMTOTHEENERGYSPECTRUM_H diff --git a/src/CountRateAnalysisView/CountRateAnalysisView.cpp b/src/CountRateAnalysisView/CountRateAnalysisView.cpp index 988086a..3f31803 100644 --- a/src/CountRateAnalysisView/CountRateAnalysisView.cpp +++ b/src/CountRateAnalysisView/CountRateAnalysisView.cpp @@ -91,7 +91,7 @@ void CountRateAnalysisView::setData(QVector data) const qint64 ns = (info.dTime * 5) / NS_PER_SECOND; const int nidx = static_cast(ns / nInv); // 整数除法,速度快 if (nidx < nVecSize) { - ++vec[nidx]; // 使用 ++ 而非 vec[nidx]++ + ++vec[nidx]; if ( y_max < vec[nidx] ) y_max = vec[nidx]; } @@ -118,7 +118,6 @@ void CountRateAnalysisView::setData(QVector data) // 刷新绘图 plot->replot(); - } QVector CountRateAnalysisView::getParticleInjectTimeData(QString path) @@ -134,17 +133,17 @@ QVector CountRateAnalysisView::getParticleInjectTimeData(QSt // 逐行读取 while (in.read_row(board, channel, energy, time_count)) { - int detector = board + channel * 8; - lineNumber++; - if(detector >= 32) - { - continue; - } - ParticleInjectTime rec; - rec.index = lineNumber; - rec.dEnergy = energy; - rec.dTime = time_count; - records.append(rec); + int detector = board + channel * 8; + lineNumber++; + if(detector >= 32) + { + continue; + } + ParticleInjectTime rec; + rec.index = lineNumber; + rec.dEnergy = energy; + rec.dTime = time_count; + records.append(rec); } return records; diff --git a/src/EfficiencyScale.ui b/src/EfficiencyScale.ui index 84db787..32ef209 100644 --- a/src/EfficiencyScale.ui +++ b/src/EfficiencyScale.ui @@ -6,20 +6,20 @@ 0 0 - 1173 - 709 + 1498 + 890 Dialog - + - + 效率刻度管理列表 - + 0 @@ -33,19 +33,19 @@ 0 - + - + - + 添加 - + 删除 @@ -57,21 +57,21 @@ - + - + - + - + 效率刻度信息 - + - + - + 85 @@ -87,10 +87,10 @@ - + - + 85 @@ -106,7 +106,7 @@ - + 0 @@ -121,18 +121,48 @@ - + - + - + + + 通道: + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + 保存 - + 另存为 @@ -143,22 +173,22 @@ - + 公式拟合 - + - + - 拟合公式: + 拐点以上拟合公式: - + - + 0 @@ -168,7 +198,7 @@ - + 拟合 @@ -177,66 +207,68 @@ - - - - 287 - 0 - - + - y = a + bx + 拐点以下拟合公式: - - - - 287 - 0 - - - - a = 1.21823, b = -5.0542 - - + + + + + + 0 + 0 + + + + + + + + 拟合 + + + + - + Qt::Horizontal - + 效率刻度拟合数据 - + - + 新增 - + 删除 - + Qt::Horizontal @@ -253,11 +285,11 @@ - + - + 0 @@ -274,7 +306,7 @@ 0 - + 0 @@ -286,7 +318,7 @@ - + 0 @@ -298,17 +330,7 @@ - 序号 - - - - - 能量(key) - - - - - 净计数率 + 能量 diff --git a/src/EnergyCountPeakFitView/EnergyCountPeakFitView.cpp b/src/EnergyCountPeakFitView/EnergyCountPeakFitView.cpp index cdaa860..fb662c0 100644 --- a/src/EnergyCountPeakFitView/EnergyCountPeakFitView.cpp +++ b/src/EnergyCountPeakFitView/EnergyCountPeakFitView.cpp @@ -754,6 +754,17 @@ void EnergyCountPeakFitView::updateHistoryDialogWithSelection(const QListdetach(); // 从绘图面板解绑 + delete marker; // 销毁对象 + } + _roiMarkers.clear(); + _plot->replot(); // 刷新画布清除线条 +} + void EnergyCountPeakFitView::clearFitCurves() { @@ -1599,21 +1610,23 @@ void EnergyCountPeakFitView::onHistoryDlgClosed() void EnergyCountPeakFitView::onActionRoiTriggered() { + clearAllRoiMarkers(); _roi->show(); } void EnergyCountPeakFitView::slot_roi_data(ROIItem &item) { + clearAllRoiMarkers(); // 第一组:起始1、结束1 红色竖线,必须存在才插入,所以一定绘制 - createVLine(item.s1, Qt::red, 1.2); - createVLine(item.e1, Qt::red, 1.2); + _roiMarkers.append(createVLine(item.s1, Qt::red, 1.2)); + _roiMarkers.append(createVLine(item.e1, Qt::red, 1.2)); // 第二组:起始2、结束2 有有效数值才绘制,无值跳过 bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0)); if (secondGroupValid) { - createVLine(item.s2, Qt::blue, 1.2); - createVLine(item.e2, Qt::blue, 1.2); + _roiMarkers.append(createVLine(item.s2, Qt::blue, 1.2)); + _roiMarkers.append(createVLine(item.e2, Qt::blue, 1.2)); } _plot->replot(); } diff --git a/src/EnergyCountPeakFitView/EnergyCountPeakFitView.h b/src/EnergyCountPeakFitView/EnergyCountPeakFitView.h index e0ba4fc..7c09be9 100644 --- a/src/EnergyCountPeakFitView/EnergyCountPeakFitView.h +++ b/src/EnergyCountPeakFitView/EnergyCountPeakFitView.h @@ -133,6 +133,7 @@ private: QList createFitCurve(const PeakFitResult& result, arma::vec xVec); // 更新历史对话框并保持指定的选中状态 void updateHistoryDialogWithSelection(const QList& selectedRefs); + void clearAllRoiMarkers(); // 清空所有ROI竖线标记 signals: void newFitResultAdded(); @@ -172,6 +173,8 @@ private: RegionOfInterest *_roi; + QList _roiMarkers; + }; #endif // ENERGYCOUNTPEAKFITVIEW_H diff --git a/src/EnergyCountPlotView/EnergyCountPlotView.cpp b/src/EnergyCountPlotView/EnergyCountPlotView.cpp index fd563e2..c36b474 100644 --- a/src/EnergyCountPlotView/EnergyCountPlotView.cpp +++ b/src/EnergyCountPlotView/EnergyCountPlotView.cpp @@ -165,6 +165,17 @@ QwtPlotMarker *EnergyCountPlotView::createVLine(double x, Qt::GlobalColor color, return marker; } +void EnergyCountPlotView::clearAllRoiMarkers() +{ + for (auto marker : _roiMarkers) + { + marker->detach(); // 从绘图面板解绑 + delete marker; // 销毁对象 + } + _roiMarkers.clear(); + _plot->replot(); // 刷新画布清除线条 +} + void EnergyCountPlotView::updateView(const QMap& data_files_set) { // 清除现有所有曲线 @@ -279,21 +290,24 @@ void EnergyCountPlotView::onActionPlotConfigure() void EnergyCountPlotView::onActionRoiTriggered() { + clearAllRoiMarkers(); _roi->show(); } void EnergyCountPlotView::slot_roi_data(ROIItem &item) { + clearAllRoiMarkers(); + // 第一组:起始1、结束1 红色竖线,必须存在才插入,所以一定绘制 - createVLine(item.s1, Qt::red, 1.2); - createVLine(item.e1, Qt::red, 1.2); + _roiMarkers.append(createVLine(item.s1, Qt::red, 1.2)); + _roiMarkers.append(createVLine(item.e1, Qt::red, 1.2)); // 第二组:起始2、结束2 有有效数值才绘制,无值跳过 bool secondGroupValid = !(qIsNaN(item.s2) || qIsNaN(item.e2) || (item.s2 == 0 && item.e2 == 0)); if (secondGroupValid) { - createVLine(item.s2, Qt::blue, 1.2); - createVLine(item.e2, Qt::blue, 1.2); + _roiMarkers.append(createVLine(item.s2, Qt::blue, 1.2)); + _roiMarkers.append(createVLine(item.e2, Qt::blue, 1.2)); } _plot->replot(); } diff --git a/src/EnergyCountPlotView/EnergyCountPlotView.h b/src/EnergyCountPlotView/EnergyCountPlotView.h index ad961e4..8f0d277 100644 --- a/src/EnergyCountPlotView/EnergyCountPlotView.h +++ b/src/EnergyCountPlotView/EnergyCountPlotView.h @@ -26,6 +26,7 @@ private: void setupMenu(); void loadDataFromFile(const QString &data_name, const QString& filename); QwtPlotMarker* createVLine(double x, Qt::GlobalColor color, double lineWidth = 1.0); // 创建垂直标记竖线 + void clearAllRoiMarkers(); // 清空所有ROI竖线标记 private slots: void onActionCurveShowSetting(); @@ -40,6 +41,8 @@ private: double _x_max = 0.0f; double _y_max = 0.0f; RegionOfInterest *_roi; + QList _roiMarkers; + }; #endif // ENERGYCOUNTPLOTVIEW_H diff --git a/src/EnergyScaleForm.cpp b/src/EnergyScaleForm.cpp index 2c6ae56..bda8461 100644 --- a/src/EnergyScaleForm.cpp +++ b/src/EnergyScaleForm.cpp @@ -220,7 +220,6 @@ QMap EnergyScaleForm::parseJsonToChannels(const QString &f } else { errorMsg += QString("通道 %1 缺少 FwhmFitResultCoeffs 字段\n").arg(channelName); } - result.insert(channelName, chData); } @@ -357,7 +356,6 @@ void EnergyScaleForm::clearPlot() _fitCurve->detach(); _plot->detachItems(QwtPlotItem::Rtti_PlotCurve, false); _plot->replot(); - } QVector EnergyScaleForm::generateFitCurvePoints(const ChannelData &chData) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 80a520c..4eb80a0 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -752,11 +752,11 @@ void MainWindow::onParticleDatarefresh() ProjectList::Instance()->SetNodeStatus(particleData,status,true); updataTable(); } + void MainWindow::onAddressCountViewNeedRefresh() { MeasureAnalysisProjectModel *pro_model = ProjectList::Instance()->GetCurrentProjectModel(); if (!pro_model) return; - bool status_ok = !pro_model->GetChannelAddressCountDataFilenameList().isEmpty(); QString status = status_ok ? QStringLiteral(u"有效") : QStringLiteral(u"无效"); QString item_name = QStringLiteral(u"道址计数谱"); @@ -879,6 +879,11 @@ void MainWindow::onParticleEnergyDataUpdated(const QString &energySpectrumFilena } void MainWindow::on_action_analysisReport_triggered() { + auto project_model = ProjectList::Instance()->GetCurrentProjectModel(); + if (project_model == nullptr) { + QMessageBox::information(this, "提示:", "请先加载项目!"); + return; + } ReportWidget *widget = new ReportWidget(); widget->show(); } diff --git a/src/NuclideAnalysisView/NuclideAnalysisView.cpp b/src/NuclideAnalysisView/NuclideAnalysisView.cpp index 231a4f8..0a1e9f7 100644 --- a/src/NuclideAnalysisView/NuclideAnalysisView.cpp +++ b/src/NuclideAnalysisView/NuclideAnalysisView.cpp @@ -194,7 +194,6 @@ void NuclideAnalysisView::setupPlot() _plot->canvas()->setMouseTracking(true); // 给canvas安装事件过滤器,捕获鼠标点击 _plot->canvas()->installEventFilter(this); - } void NuclideAnalysisView::setupMenu() diff --git a/src/analysisReport/reportwidget.cpp b/src/analysisReport/reportwidget.cpp index 3540a6a..2d6a3a9 100644 --- a/src/analysisReport/reportwidget.cpp +++ b/src/analysisReport/reportwidget.cpp @@ -32,7 +32,7 @@ void ReportWidget::setupUi() // 顶部按钮栏 auto* btnLayout = new QHBoxLayout(); - m_sampleBtn = new QPushButton("加载示例数据", this); + m_sampleBtn = new QPushButton("加载数据", this); m_refreshBtn = new QPushButton("刷新报告", this); m_exportHtmlBtn = new QPushButton("导出HTML", this); m_exportWordBtn = new QPushButton("导出Word", this); @@ -472,10 +472,6 @@ void ReportWidget::exportText() void ReportWidget::loadSampleData() { auto project_model = ProjectList::Instance()->GetCurrentProjectModel(); - if (project_model == nullptr) { - QMessageBox::information(this, "提示:", "请先加载项目!"); - return; - } //获取当前可执行目录下 QString jsonPath = project_model->GetProjectDir() + "/report_params.json"; m_data.loadReportParamsJson(jsonPath);