2026-04-07 18:15:20 +08:00
|
|
|
|
#include "TwoDSpectralCompliance.h"
|
|
|
|
|
|
#include "ui_TwoDSpectralCompliance.h"
|
|
|
|
|
|
#include "CustomQwtPlot.h"
|
|
|
|
|
|
#include <QwtPlotCanvas>
|
|
|
|
|
|
#include <QwtText>
|
|
|
|
|
|
#include <QwtLegend>
|
|
|
|
|
|
#include <QwtPlotSpectrogram>
|
|
|
|
|
|
#include <QwtLinearColorMap>
|
|
|
|
|
|
#include <QwtMatrixRasterData>
|
|
|
|
|
|
#include <QHBoxLayout>
|
2026-04-09 17:55:20 +08:00
|
|
|
|
#include <QVBoxLayout>
|
2026-04-07 18:15:20 +08:00
|
|
|
|
#include <QFile>
|
|
|
|
|
|
#include <QTextStream>
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
#include <QwtInterval>
|
|
|
|
|
|
#include <qwt_matrix_raster_data.h>
|
|
|
|
|
|
#include <algorithm>
|
2026-04-09 17:55:20 +08:00
|
|
|
|
#include <QFormLayout>
|
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
|
#include <QPushButton>
|
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
|
#include <QSet>
|
2026-05-09 16:50:34 +08:00
|
|
|
|
#include "BusyIndicator.h"
|
|
|
|
|
|
#include <QThread>
|
|
|
|
|
|
|
2026-04-07 18:15:20 +08:00
|
|
|
|
class HeatMapColorMap : public QwtLinearColorMap
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
2026-04-09 17:55:20 +08:00
|
|
|
|
HeatMapColorMap() : QwtLinearColorMap(Qt::blue, Qt::red)
|
2026-04-07 18:15:20 +08:00
|
|
|
|
{
|
2026-04-09 17:55:20 +08:00
|
|
|
|
addColorStop(0.25, Qt::cyan);
|
2026-04-07 18:15:20 +08:00
|
|
|
|
addColorStop(0.5, Qt::green);
|
|
|
|
|
|
addColorStop(0.75, Qt::yellow);
|
2026-04-09 17:55:20 +08:00
|
|
|
|
addColorStop(0.90, Qt::darkRed);
|
2026-04-07 18:15:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
|
|
|
|
|
|
MeasureAnalysisView(parent),
|
|
|
|
|
|
ui(new Ui::TwoDSpectralCompliance)
|
|
|
|
|
|
{
|
|
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
QHBoxLayout* layout = new QHBoxLayout(this);
|
|
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
this->_plot = new CustomQwtPlot(this);
|
|
|
|
|
|
layout->addWidget(this->_plot);
|
|
|
|
|
|
setupPlot();
|
2026-04-09 17:55:20 +08:00
|
|
|
|
createFloatingInfoWidget();
|
2026-05-09 16:50:34 +08:00
|
|
|
|
_busy_indicator = new BusyIndicator(this);
|
|
|
|
|
|
|
2026-04-07 18:15:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TwoDSpectralCompliance::~TwoDSpectralCompliance()
|
|
|
|
|
|
{
|
|
|
|
|
|
delete ui;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::InitViewWorkspace(const QString &project_name)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(project_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (data_files_set.isEmpty())
|
|
|
|
|
|
return;
|
|
|
|
|
|
QString csvFile = data_files_set.first().toString();
|
|
|
|
|
|
if (csvFile.isEmpty())
|
|
|
|
|
|
return;
|
2026-05-09 16:50:34 +08:00
|
|
|
|
auto functionToRun = [this, csvFile](){
|
|
|
|
|
|
_busy_indicator->Start();
|
2026-04-07 18:15:20 +08:00
|
|
|
|
readCsv(csvFile);
|
|
|
|
|
|
generateSurfaceData();
|
|
|
|
|
|
updateSpectrogram();
|
2026-05-09 16:50:34 +08:00
|
|
|
|
_busy_indicator->Stop();
|
|
|
|
|
|
};
|
|
|
|
|
|
QThread* load_data_thread = QThread::create(functionToRun);
|
|
|
|
|
|
load_data_thread->start();
|
2026-04-07 18:15:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-09 17:55:20 +08:00
|
|
|
|
|
2026-04-07 18:15:20 +08:00
|
|
|
|
void TwoDSpectralCompliance::setupPlot()
|
|
|
|
|
|
{
|
|
|
|
|
|
_plot->setCanvasBackground(Qt::white);
|
|
|
|
|
|
QwtPlotCanvas* canvas = qobject_cast<QwtPlotCanvas*>(_plot->canvas());
|
|
|
|
|
|
if (canvas)
|
|
|
|
|
|
canvas->setFrameStyle(QFrame::NoFrame);
|
|
|
|
|
|
|
|
|
|
|
|
QFont font = this->font();
|
|
|
|
|
|
font.setBold(false);
|
2026-04-09 17:55:20 +08:00
|
|
|
|
QwtText energy_label = QStringLiteral(u"初级粒子能量");
|
2026-04-07 18:15:20 +08:00
|
|
|
|
energy_label.setFont(font);
|
2026-04-09 17:55:20 +08:00
|
|
|
|
QwtText count_label = QStringLiteral(u"次级粒子能量");
|
2026-04-07 18:15:20 +08:00
|
|
|
|
count_label.setFont(font);
|
|
|
|
|
|
_plot->setAxisTitle(QwtPlot::xBottom, energy_label);
|
|
|
|
|
|
_plot->setAxisTitle(QwtPlot::yLeft, count_label);
|
|
|
|
|
|
|
|
|
|
|
|
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
|
|
|
|
|
|
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
|
|
|
|
|
|
|
|
|
|
|
|
_plot->enableAxis(QwtPlot::xBottom);
|
|
|
|
|
|
_plot->enableAxis(QwtPlot::yLeft);
|
|
|
|
|
|
|
|
|
|
|
|
QwtLegend* legend = new QwtLegend();
|
|
|
|
|
|
legend->setDefaultItemMode(QwtLegendData::ReadOnly);
|
|
|
|
|
|
_plot->insertLegend(legend, QwtPlot::RightLegend);
|
|
|
|
|
|
|
|
|
|
|
|
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
|
|
|
|
|
|
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
|
|
|
|
|
|
|
|
|
|
|
|
_spectrogram = new QwtPlotSpectrogram();
|
|
|
|
|
|
_spectrogram->setColorMap(new HeatMapColorMap());
|
|
|
|
|
|
_spectrogram->attach(_plot);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::readCsv(const QString &filename)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_rawData.clear();
|
|
|
|
|
|
QFile file(filename);
|
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
2026-04-09 17:55:20 +08:00
|
|
|
|
qWarning() << QStringLiteral(u"无法打开文件:") << filename;
|
2026-04-07 18:15:20 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QTextStream stream(&file);
|
2026-04-09 17:55:20 +08:00
|
|
|
|
QString header = stream.readLine();
|
2026-04-07 18:15:20 +08:00
|
|
|
|
Q_UNUSED(header);
|
|
|
|
|
|
|
|
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
|
|
QString line = stream.readLine();
|
|
|
|
|
|
if (line.isEmpty())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
QStringList fields = line.split(',');
|
|
|
|
|
|
if (fields.size() < 5)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
EventData data;
|
|
|
|
|
|
data.eventId = fields[0].toInt();
|
|
|
|
|
|
data.board = fields[1].toInt();
|
|
|
|
|
|
data.channel = fields[2].toInt();
|
|
|
|
|
|
data.energy = fields[3].toDouble();
|
|
|
|
|
|
data.timeCounter = fields[4].toULongLong();
|
|
|
|
|
|
m_rawData.append(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::generateSurfaceData()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_surfaceData.clear();
|
|
|
|
|
|
if (m_rawData.isEmpty())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
QMap<int, QVector<EventData>> eventMap;
|
|
|
|
|
|
for (const auto& ev : m_rawData) {
|
|
|
|
|
|
eventMap[ev.eventId].append(ev);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QMap<QPair<float, float>, int> countMap;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto it = eventMap.begin(); it != eventMap.end(); ++it) {
|
|
|
|
|
|
const auto& events = it.value();
|
|
|
|
|
|
if (events.isEmpty())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
float primaryEnergy = events[0].energy;
|
|
|
|
|
|
float secondarySum = 0.0f;
|
|
|
|
|
|
for (int i = 1; i < events.size(); ++i) {
|
|
|
|
|
|
secondarySum += events[i].energy;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto key = qMakePair(primaryEnergy, secondarySum);
|
|
|
|
|
|
countMap[key]++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (auto it = countMap.begin(); it != countMap.end(); ++it) {
|
|
|
|
|
|
TwoSurfacePoint point;
|
|
|
|
|
|
point.primaryEnergy = it.key().first;
|
|
|
|
|
|
point.secondaryEnergySum = it.key().second;
|
|
|
|
|
|
point.count = it.value();
|
|
|
|
|
|
m_surfaceData.append(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::updateSpectrogram()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_surfaceData.isEmpty()) {
|
|
|
|
|
|
_spectrogram->setData(new QwtMatrixRasterData());
|
|
|
|
|
|
_plot->replot();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float minPrim = 1e9f, maxPrim = -1e9f;
|
|
|
|
|
|
float minSec = 1e9f, maxSec = -1e9f;
|
|
|
|
|
|
int maxCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& pt : m_surfaceData) {
|
|
|
|
|
|
minPrim = std::min(minPrim, pt.primaryEnergy);
|
|
|
|
|
|
maxPrim = std::max(maxPrim, pt.primaryEnergy);
|
|
|
|
|
|
minSec = std::min(minSec, pt.secondaryEnergySum);
|
|
|
|
|
|
maxSec = std::max(maxSec, pt.secondaryEnergySum);
|
|
|
|
|
|
maxCount = std::max(maxCount, pt.count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double primRange = maxPrim - minPrim;
|
|
|
|
|
|
double secRange = maxSec - minSec;
|
|
|
|
|
|
if (primRange < 1e-6) primRange = 1.0;
|
|
|
|
|
|
if (secRange < 1e-6) secRange = 1.0;
|
|
|
|
|
|
double primStart = minPrim - primRange * 0.05;
|
|
|
|
|
|
double primEnd = maxPrim + primRange * 0.05;
|
|
|
|
|
|
double secStart = minSec - secRange * 0.05;
|
|
|
|
|
|
double secEnd = maxSec + secRange * 0.05;
|
|
|
|
|
|
|
2026-04-09 17:55:20 +08:00
|
|
|
|
const int numCols = 200;
|
|
|
|
|
|
const int numRows = 200;
|
2026-04-07 18:15:20 +08:00
|
|
|
|
|
|
|
|
|
|
double stepX = (primEnd - primStart) / numCols;
|
|
|
|
|
|
double stepY = (secEnd - secStart) / numRows;
|
|
|
|
|
|
|
|
|
|
|
|
QVector<double> zValues(numRows * numCols, 0.0);
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& pt : m_surfaceData) {
|
|
|
|
|
|
int col = static_cast<int>((pt.primaryEnergy - primStart) / stepX);
|
|
|
|
|
|
int row = static_cast<int>((pt.secondaryEnergySum - secStart) / stepY);
|
|
|
|
|
|
col = qBound(0, col, numCols - 1);
|
|
|
|
|
|
row = qBound(0, row, numRows - 1);
|
|
|
|
|
|
zValues[row * numCols + col] += pt.count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QwtMatrixRasterData* data = new QwtMatrixRasterData();
|
|
|
|
|
|
data->setInterval(Qt::XAxis, QwtInterval(primStart, primEnd));
|
|
|
|
|
|
data->setInterval(Qt::YAxis, QwtInterval(secStart, secEnd));
|
|
|
|
|
|
data->setInterval(Qt::ZAxis, QwtInterval(0, maxCount));
|
|
|
|
|
|
data->setValueMatrix(zValues, numCols);
|
|
|
|
|
|
|
|
|
|
|
|
_spectrogram->setData(data);
|
|
|
|
|
|
_plot->setAxisScale(QwtPlot::xBottom, primStart, primEnd);
|
|
|
|
|
|
_plot->setAxisScale(QwtPlot::yLeft, secStart, secEnd);
|
|
|
|
|
|
_plot->replot();
|
|
|
|
|
|
}
|
2026-04-09 17:55:20 +08:00
|
|
|
|
void TwoDSpectralCompliance::createFloatingInfoWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 悬浮窗口
|
|
|
|
|
|
m_floatingWidget = new QWidget(this);
|
|
|
|
|
|
m_floatingWidget->setObjectName("FloatingInfoWidget");
|
|
|
|
|
|
m_floatingWidget->setStyleSheet(
|
|
|
|
|
|
"QWidget#FloatingInfoWidget {"
|
|
|
|
|
|
" background-color: rgba(240, 240, 240, 240);"
|
|
|
|
|
|
" border: 1px solid gray;"
|
|
|
|
|
|
" border-radius: 5px;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
);
|
|
|
|
|
|
m_floatingWidget->setFixedSize(320, 220);
|
|
|
|
|
|
m_floatingWidget->setAttribute(Qt::WA_TranslucentBackground, false);
|
|
|
|
|
|
|
|
|
|
|
|
QVBoxLayout* mainLayout = new QVBoxLayout(m_floatingWidget);
|
|
|
|
|
|
mainLayout->setSpacing(5);
|
|
|
|
|
|
mainLayout->setContentsMargins(8, 8, 8, 8);
|
|
|
|
|
|
|
|
|
|
|
|
// 标题栏(可拖动,并包含隐藏按钮)
|
|
|
|
|
|
QWidget* titleBar = new QWidget();
|
|
|
|
|
|
QHBoxLayout* titleLayout = new QHBoxLayout(titleBar);
|
|
|
|
|
|
titleLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
QLabel* titleLabel = new QLabel(QStringLiteral(u"数据统计信息"));
|
|
|
|
|
|
titleLabel->setStyleSheet("font-weight: bold;");
|
|
|
|
|
|
titleLayout->addWidget(titleLabel);
|
|
|
|
|
|
titleLayout->addStretch();
|
|
|
|
|
|
QPushButton* hideBtn = new QPushButton(QStringLiteral("−"));
|
|
|
|
|
|
hideBtn->setFixedSize(20, 20);
|
2026-04-13 18:17:01 +08:00
|
|
|
|
hideBtn->setText(QStringLiteral(u"X"));
|
2026-04-09 17:55:20 +08:00
|
|
|
|
hideBtn->setStyleSheet("border: none; font-weight: bold;");
|
|
|
|
|
|
titleLayout->addWidget(hideBtn);
|
|
|
|
|
|
mainLayout->addWidget(titleBar);
|
|
|
|
|
|
|
|
|
|
|
|
QWidget* contentWidget = new QWidget();
|
|
|
|
|
|
QFormLayout* formLayout = new QFormLayout(contentWidget);
|
|
|
|
|
|
formLayout->setSpacing(8);
|
|
|
|
|
|
formLayout->setLabelAlignment(Qt::AlignRight);
|
|
|
|
|
|
|
|
|
|
|
|
m_totalEventsEdit = new QLineEdit;
|
|
|
|
|
|
m_totalEventsEdit->setReadOnly(true);
|
|
|
|
|
|
m_totalEventsEdit->setFixedWidth(130);
|
|
|
|
|
|
|
|
|
|
|
|
m_totalPointsEdit = new QLineEdit;
|
|
|
|
|
|
m_totalPointsEdit->setReadOnly(true);
|
|
|
|
|
|
m_totalPointsEdit->setFixedWidth(130);
|
|
|
|
|
|
m_maxCountEdit = new QLineEdit;
|
|
|
|
|
|
m_maxCountEdit->setReadOnly(true);
|
|
|
|
|
|
m_maxCountEdit->setFixedWidth(130);
|
|
|
|
|
|
|
|
|
|
|
|
m_primRangeEdit = new QLineEdit;
|
|
|
|
|
|
m_primRangeEdit->setReadOnly(true);
|
|
|
|
|
|
m_primRangeEdit->setFixedWidth(130);
|
|
|
|
|
|
|
|
|
|
|
|
m_secRangeEdit = new QLineEdit;
|
|
|
|
|
|
m_secRangeEdit->setReadOnly(true);
|
|
|
|
|
|
m_secRangeEdit->setFixedWidth(130);
|
|
|
|
|
|
|
|
|
|
|
|
formLayout->addRow(QStringLiteral(u"总事件数:"), m_totalEventsEdit);
|
|
|
|
|
|
formLayout->addRow(QStringLiteral(u"有效数据点:"), m_totalPointsEdit);
|
|
|
|
|
|
formLayout->addRow(QStringLiteral(u"最大计数:"), m_maxCountEdit);
|
|
|
|
|
|
formLayout->addRow(QStringLiteral(u"初级能量范围:"), m_primRangeEdit);
|
|
|
|
|
|
formLayout->addRow(QStringLiteral(u"次级能量和范围:"), m_secRangeEdit);
|
|
|
|
|
|
|
|
|
|
|
|
mainLayout->addWidget(contentWidget);
|
|
|
|
|
|
mainLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
|
|
connect(hideBtn, &QPushButton::clicked, this, &TwoDSpectralCompliance::hideFloatingWidget);
|
|
|
|
|
|
|
|
|
|
|
|
titleBar->setCursor(Qt::SizeAllCursor);
|
|
|
|
|
|
m_floatingWidget->installEventFilter(this);
|
|
|
|
|
|
|
|
|
|
|
|
m_showButton = new QPushButton(this);
|
|
|
|
|
|
m_showButton->setFixedSize(28, 28);
|
|
|
|
|
|
m_showButton->setToolTip(QStringLiteral(u"显示信息窗口"));
|
|
|
|
|
|
m_showButton->setStyleSheet(
|
|
|
|
|
|
"QPushButton {"
|
|
|
|
|
|
" background-color: rgba(200,200,200,200);"
|
|
|
|
|
|
" border: 1px solid #888;"
|
|
|
|
|
|
" border-radius: 14px;"
|
|
|
|
|
|
" font-weight: bold;"
|
|
|
|
|
|
"}"
|
|
|
|
|
|
"QPushButton:hover { background-color: rgba(150,150,150,200); }"
|
|
|
|
|
|
);
|
2026-04-13 18:17:01 +08:00
|
|
|
|
m_showButton->setText(QStringLiteral(u"⊕"));
|
2026-04-09 17:55:20 +08:00
|
|
|
|
connect(m_showButton, &QPushButton::clicked, this, &TwoDSpectralCompliance::showFloatingWidget);
|
|
|
|
|
|
|
|
|
|
|
|
m_floatingWidget->move(10, 10);
|
|
|
|
|
|
updateShowButtonPosition();
|
|
|
|
|
|
m_floatingWidget->hide();
|
|
|
|
|
|
m_showButton->show();
|
|
|
|
|
|
|
|
|
|
|
|
// m_floatingWidget->raise();
|
|
|
|
|
|
updateInfoContent();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::hideFloatingWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_floatingWidget->hide();
|
|
|
|
|
|
m_showButton->show();
|
|
|
|
|
|
updateShowButtonPosition();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::showFloatingWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_floatingWidget->show();
|
|
|
|
|
|
m_floatingWidget->raise();
|
|
|
|
|
|
m_showButton->hide();
|
|
|
|
|
|
updateInfoContent(); // 刷新内容
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::updateShowButtonPosition()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_showButton && m_showButton->isVisible()) {
|
|
|
|
|
|
m_showButton->move(10, 10);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::updateInfoContent()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_totalEventsEdit)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_surfaceData.isEmpty()) {
|
|
|
|
|
|
m_totalEventsEdit->setText(QStringLiteral(u"无数据"));
|
|
|
|
|
|
m_totalPointsEdit->setText(QStringLiteral(u"无数据"));
|
|
|
|
|
|
m_maxCountEdit->setText(QStringLiteral(u"无数据"));
|
|
|
|
|
|
m_primRangeEdit->setText(QStringLiteral(u"无数据"));
|
|
|
|
|
|
m_secRangeEdit->setText(QStringLiteral(u"无数据"));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int totalPoints = m_surfaceData.size();
|
|
|
|
|
|
int maxCount = 0;
|
|
|
|
|
|
float minPrim = 1e9f, maxPrim = -1e9f;
|
|
|
|
|
|
float minSec = 1e9f, maxSec = -1e9f;
|
|
|
|
|
|
for (const auto& pt : m_surfaceData) {
|
|
|
|
|
|
minPrim = std::min(minPrim, pt.primaryEnergy);
|
|
|
|
|
|
maxPrim = std::max(maxPrim, pt.primaryEnergy);
|
|
|
|
|
|
minSec = std::min(minSec, pt.secondaryEnergySum);
|
|
|
|
|
|
maxSec = std::max(maxSec, pt.secondaryEnergySum);
|
|
|
|
|
|
maxCount = std::max(maxCount, pt.count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QSet<int> eventIds;
|
|
|
|
|
|
for (const auto& ev : m_rawData) {
|
|
|
|
|
|
eventIds.insert(ev.eventId);
|
|
|
|
|
|
}
|
|
|
|
|
|
int totalEvents = eventIds.size();
|
|
|
|
|
|
|
|
|
|
|
|
m_totalEventsEdit->setText(QString::number(totalEvents));
|
|
|
|
|
|
m_totalPointsEdit->setText(QString::number(totalPoints));
|
|
|
|
|
|
m_maxCountEdit->setText(QString::number(maxCount));
|
|
|
|
|
|
m_primRangeEdit->setText(QString("[%1, %2]").arg(minPrim, 0, 'f', 2).arg(maxPrim, 0, 'f', 2));
|
|
|
|
|
|
m_secRangeEdit->setText(QString("[%1, %2]").arg(minSec, 0, 'f', 2).arg(maxSec, 0, 'f', 2));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::resizeEvent(QResizeEvent *event)
|
|
|
|
|
|
{
|
|
|
|
|
|
QWidget::resizeEvent(event);
|
|
|
|
|
|
updateShowButtonPosition();
|
|
|
|
|
|
if (m_floatingWidget && m_floatingWidget->isVisible()) {
|
|
|
|
|
|
// 限制悬浮窗口不超出父窗口边界
|
|
|
|
|
|
QRect rect = m_floatingWidget->geometry();
|
|
|
|
|
|
int newX = qBound(0, rect.x(), width() - rect.width());
|
|
|
|
|
|
int newY = qBound(0, rect.y(), height() - rect.height());
|
|
|
|
|
|
if (newX != rect.x() || newY != rect.y())
|
|
|
|
|
|
m_floatingWidget->move(newX, newY);
|
|
|
|
|
|
m_floatingWidget->raise();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (obj == m_floatingWidget) {
|
|
|
|
|
|
if (event->type() == QEvent::MouseButtonPress) {
|
|
|
|
|
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
|
|
|
|
|
if (mouseEvent->button() == Qt::LeftButton) {
|
|
|
|
|
|
m_dragging = true;
|
|
|
|
|
|
m_dragPosition = mouseEvent->globalPos() - m_floatingWidget->frameGeometry().topLeft();
|
|
|
|
|
|
event->accept();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (event->type() == QEvent::MouseMove) {
|
|
|
|
|
|
if (m_dragging) {
|
|
|
|
|
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
|
|
|
|
|
m_floatingWidget->move(mouseEvent->globalPos() - m_dragPosition);
|
|
|
|
|
|
event->accept();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
|
|
|
|
|
if (m_dragging) {
|
|
|
|
|
|
m_dragging = false;
|
|
|
|
|
|
event->accept();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return QWidget::eventFilter(obj, event);
|
|
|
|
|
|
}
|
2026-05-09 16:50:34 +08:00
|
|
|
|
|
|
|
|
|
|
void TwoDSpectralCompliance::showEvent(QShowEvent *e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(e);
|
|
|
|
|
|
if (_busy_indicator) {
|
|
|
|
|
|
_busy_indicator->setGeometry(this->rect());
|
|
|
|
|
|
this->update();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|