1、修改添加图表的还原

2、修改bug
3、更新测量数据接收代码
This commit is contained in:
徐海 2026-05-12 20:57:54 +08:00
parent cbb56426ec
commit d1d5b1d3d0
21 changed files with 539 additions and 555 deletions

View File

@ -1,34 +1,34 @@
#include "TwoDSpectralCompliance.h"
#include "ui_TwoDSpectralCompliance.h"
#include "BusyIndicator.h"
#include "CustomQwtPlot.h"
#include <QwtPlotCanvas>
#include <QwtText>
#include <QwtLegend>
#include <QwtPlotSpectrogram>
#include <QwtLinearColorMap>
#include <QwtMatrixRasterData>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFile>
#include <QTextStream>
#include "ui_TwoDSpectralCompliance.h"
#include <QDebug>
#include <cmath>
#include <QwtInterval>
#include <qwt_matrix_raster_data.h>
#include <algorithm>
#include <QFile>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QMouseEvent>
#include <QPushButton>
#include <QSet>
#include "BusyIndicator.h"
#include <QTextStream>
#include <QThread>
#include <QVBoxLayout>
#include <QwtInterval>
#include <QwtLegend>
#include <QwtLinearColorMap>
#include <QwtMatrixRasterData>
#include <QwtPlotCanvas>
#include <QwtPlotSpectrogram>
#include <QwtText>
#include <algorithm>
#include <cmath>
#include <qwt_matrix_raster_data.h>
class HeatMapColorMap : public QwtLinearColorMap
{
class HeatMapColorMap : public QwtLinearColorMap {
public:
HeatMapColorMap() : QwtLinearColorMap(Qt::blue, Qt::red)
HeatMapColorMap()
: QwtLinearColorMap(Qt::blue, Qt::red)
{
addColorStop(0.25, Qt::cyan);
addColorStop(0.5, Qt::green);
@ -37,9 +37,9 @@ public:
}
};
TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
MeasureAnalysisView(parent),
ui(new Ui::TwoDSpectralCompliance)
TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget* parent)
: MeasureAnalysisView(parent)
, ui(new Ui::TwoDSpectralCompliance)
{
ui->setupUi(this);
QHBoxLayout* layout = new QHBoxLayout(this);
@ -49,7 +49,6 @@ TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
setupPlot();
createFloatingInfoWidget();
_busy_indicator = new BusyIndicator(this);
}
TwoDSpectralCompliance::~TwoDSpectralCompliance()
@ -57,30 +56,29 @@ TwoDSpectralCompliance::~TwoDSpectralCompliance()
delete ui;
}
void TwoDSpectralCompliance::InitViewWorkspace(const QString &project_name)
void TwoDSpectralCompliance::InitViewWorkspace(const QString& project_name)
{
Q_UNUSED(project_name);
}
void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
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;
auto functionToRun = [this, csvFile](){
_busy_indicator->Start();
readCsv(csvFile);
generateSurfaceData();
updateSpectrogram();
_busy_indicator->Stop();
auto functionToRun = [this, csvFile]() {
_busy_indicator->Start();
readCsv(csvFile);
generateSurfaceData();
updateSpectrogram();
_busy_indicator->Stop();
};
QThread* load_data_thread = QThread::create(functionToRun);
load_data_thread->start();
}
void TwoDSpectralCompliance::setupPlot()
{
_plot->setCanvasBackground(Qt::white);
@ -115,7 +113,7 @@ void TwoDSpectralCompliance::setupPlot()
_spectrogram->attach(_plot);
}
void TwoDSpectralCompliance::readCsv(const QString &filename)
void TwoDSpectralCompliance::readCsv(const QString& filename)
{
m_rawData.clear();
QFile file(filename);
@ -183,64 +181,65 @@ void TwoDSpectralCompliance::generateSurfaceData()
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;
const int numCols = 200;
const int numRows = 200;
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);
_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;
const int numCols = 200;
const int numRows = 200;
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();
}
void TwoDSpectralCompliance::createFloatingInfoWidget()
{
@ -252,8 +251,7 @@ void TwoDSpectralCompliance::createFloatingInfoWidget()
" 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);
@ -324,17 +322,16 @@ void TwoDSpectralCompliance::createFloatingInfoWidget()
" border-radius: 14px;"
" font-weight: bold;"
"}"
"QPushButton:hover { background-color: rgba(150,150,150,200); }"
);
"QPushButton:hover { background-color: rgba(150,150,150,200); }");
m_showButton->setText(QStringLiteral(u""));
connect(m_showButton, &QPushButton::clicked, this, &TwoDSpectralCompliance::showFloatingWidget);
m_floatingWidget->move(10, 10);
updateShowButtonPosition();
m_floatingWidget->hide();
m_showButton->show();
m_floatingWidget->hide();
m_showButton->show();
// m_floatingWidget->raise();
// m_floatingWidget->raise();
updateInfoContent();
}
@ -399,7 +396,7 @@ void TwoDSpectralCompliance::updateInfoContent()
m_secRangeEdit->setText(QString("[%1, %2]").arg(minSec, 0, 'f', 2).arg(maxSec, 0, 'f', 2));
}
void TwoDSpectralCompliance::resizeEvent(QResizeEvent *event)
void TwoDSpectralCompliance::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
updateShowButtonPosition();
@ -414,11 +411,11 @@ void TwoDSpectralCompliance::resizeEvent(QResizeEvent *event)
}
}
bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
bool TwoDSpectralCompliance::eventFilter(QObject* obj, QEvent* event)
{
if (obj == m_floatingWidget) {
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
m_dragging = true;
m_dragPosition = mouseEvent->globalPos() - m_floatingWidget->frameGeometry().topLeft();
@ -427,7 +424,7 @@ bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
}
} else if (event->type() == QEvent::MouseMove) {
if (m_dragging) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
m_floatingWidget->move(mouseEvent->globalPos() - m_dragPosition);
event->accept();
return true;
@ -443,11 +440,11 @@ bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
return QWidget::eventFilter(obj, event);
}
void TwoDSpectralCompliance::showEvent(QShowEvent *e)
void TwoDSpectralCompliance::showEvent(QShowEvent* e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}

View File

@ -1,10 +1,10 @@
#ifndef TWODSPECTRALCOMPLIANCE_H
#define TWODSPECTRALCOMPLIANCE_H
#include <QWidget>
#include <MeasureAnalysisView.h>
#include <QVector>
#include <QPoint>
#include <QVector>
#include <QWidget>
class CustomQwtPlot;
class QwtPlotSpectrogram;
@ -22,19 +22,19 @@ struct TwoSurfacePoint {
int count;
};
class TwoDSpectralCompliance : public MeasureAnalysisView
{
class TwoDSpectralCompliance : public MeasureAnalysisView {
Q_OBJECT
public:
explicit TwoDSpectralCompliance(QWidget *parent = nullptr);
explicit TwoDSpectralCompliance(QWidget* parent = nullptr);
~TwoDSpectralCompliance();
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) override;
protected:
void resizeEvent(QResizeEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
void resizeEvent(QResizeEvent* event) override;
bool eventFilter(QObject* obj, QEvent* event) override;
virtual void showEvent(QShowEvent* e) override final;
private:
@ -54,9 +54,8 @@ private slots:
void showFloatingWidget();
void hideFloatingWidget();
private:
Ui::TwoDSpectralCompliance *ui;
Ui::TwoDSpectralCompliance* ui;
CustomQwtPlot* _plot = nullptr;
QwtPlotSpectrogram* _spectrogram = nullptr;
@ -70,20 +69,19 @@ private:
QVector<EventData> m_rawData;
QVector<TwoSurfacePoint> m_surfaceData;
QWidget* m_floatingWidget = nullptr;
QPushButton* m_toggleButton = nullptr;
QPushButton* m_showButton = nullptr;
QWidget* m_floatingWidget = nullptr;
QPushButton* m_toggleButton = nullptr;
QPushButton* m_showButton = nullptr;
QLineEdit* m_totalEventsEdit = nullptr;
QLineEdit* m_totalPointsEdit = nullptr;
QLineEdit* m_maxCountEdit = nullptr;
QLineEdit* m_primRangeEdit = nullptr;
QLineEdit* m_secRangeEdit = nullptr;
QPoint m_dragPosition;
bool m_dragging = false;
BusyIndicator* _busy_indicator = nullptr;
QLineEdit* m_totalEventsEdit = nullptr;
QLineEdit* m_totalPointsEdit = nullptr;
QLineEdit* m_maxCountEdit = nullptr;
QLineEdit* m_primRangeEdit = nullptr;
QLineEdit* m_secRangeEdit = nullptr;
QPoint m_dragPosition;
bool m_dragging = false;
BusyIndicator* _busy_indicator = nullptr;
};
#endif // TWODSPECTRALCOMPLIANCE_H

View File

@ -1,33 +1,36 @@
#include "AntiConformEnergySpectrumView.h"
#include <QVBoxLayout>
#include <QwtPlotCurve>
#include <QwtPlotCanvas>
#include <QwtText>
#include "CustomQwtPlot.h"
#include <GlobalDefine.h>
#include "csv.h"
#include <QFileInfo>
#include <QThread>
#include "BusyIndicator.h"
#include <map>
#include <vector>
#include "CustomQwtPlot.h"
#include "csv.h"
#include <GlobalDefine.h>
#include <QFileInfo>
#include <QMenu>
#include <QPen>
#include <QThread>
#include <QVBoxLayout>
#include <QwtPlotCanvas>
#include <QwtPlotCurve>
#include <QwtText>
#include <algorithm>
#include <cstdint>
#include <QPen>
struct SpectrumData
{
#include <map>
#include <vector>
struct SpectrumData {
int board_id;
int channel_id;
double energy;
uint64_t timestamp;
};
AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget *parent) :
MeasureAnalysisView(parent)
AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget* parent)
: MeasureAnalysisView(parent)
{
this->setViewType(PlotFrame);
this->_menu = new QMenu(this);
setupMenu();
_plot = new CustomQwtPlot();
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(_plot);
@ -50,6 +53,7 @@ AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget *parent) :
_plot->enableAxis(QwtPlot::xBottom);
_plot->enableAxis(QwtPlot::yLeft);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
_curve = new QwtPlotCurve();
_curve->setStyle(QwtPlotCurve::Lines);
@ -63,12 +67,12 @@ AntiConformEnergySpectrumView::~AntiConformEnergySpectrumView()
{
}
void AntiConformEnergySpectrumView::InitViewWorkspace(const QString &project_name)
void AntiConformEnergySpectrumView::InitViewWorkspace(const QString& project_name)
{
Q_UNUSED(project_name);
}
void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set)
{
const QString& data_filename = data_files_set.first().toString();
if (!data_filename.isEmpty() && QFileInfo(data_filename).exists()) {
@ -77,21 +81,21 @@ void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, Q
}
}
void AntiConformEnergySpectrumView::loadAndProcess()
{
auto functionToRun = [this]() {
if (_data_filename.isEmpty()) return;
if (_data_filename.isEmpty())
return;
_busy_indicator->Start();
std::vector<SpectrumData> rawData;
io::CSVReader<4> in(QStrToSysPath(_data_filename));
in.read_header(io::ignore_extra_column,
QString(QStringLiteral(u"板卡号")).toStdString(),
QString(QStringLiteral(u"通道号")).toStdString(),
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
QString(QStringLiteral(u"时间计数")).toStdString());
QString(QStringLiteral(u"板卡号")).toStdString(),
QString(QStringLiteral(u"通道号")).toStdString(),
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
QString(QStringLiteral(u"时间计数")).toStdString());
int board, channel;
double energy;
@ -134,19 +138,21 @@ void AntiConformEnergySpectrumView::loadAndProcess()
QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() {
_curve->setSamples(vx, vy);
_plot->setAxisScale(QwtPlot::xBottom, 0, dmaxx);
_plot->setAxisScale(QwtPlot::yLeft, 0, dmaxy * 1.1);
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, dmaxx);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, dmaxy);
_plot->replot();
_busy_indicator->Stop();
}, Qt::QueuedConnection);
_busy_indicator->Stop(); }, Qt::QueuedConnection);
};
QThread* load_thread = QThread::create(functionToRun);
load_thread->start();
}
void AntiConformEnergySpectrumView::showEvent(QShowEvent *e)
void AntiConformEnergySpectrumView::onActionPlotConfigure()
{
}
void AntiConformEnergySpectrumView::showEvent(QShowEvent* e)
{
Q_UNUSED(e);
if (_busy_indicator) {
@ -155,4 +161,19 @@ void AntiConformEnergySpectrumView::showEvent(QShowEvent *e)
}
}
void AntiConformEnergySpectrumView::setupMenu()
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &AntiConformEnergySpectrumView::customContextMenuRequested, [this](const QPoint& pos) {
this->_menu->exec(this->mapToGlobal(pos));
});
QAction* action_plot_reset = this->_menu->addAction(QStringLiteral(u"还原"));
action_plot_reset->setObjectName("plot_reset");
connect(action_plot_reset, &QAction::triggered, [this]() {
this->_plot->ResetPlot();
});
this->_menu->addSeparator();
QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置"));
action_plot_config->setObjectName("plot_config");
connect(action_plot_config, &QAction::triggered, this, &AntiConformEnergySpectrumView::onActionPlotConfigure);
}

View File

@ -3,15 +3,15 @@
#include "MeasureAnalysisView.h"
class QMenu;
class CustomQwtPlot;
class QwtPlotCurve;
class BusyIndicator;
class AntiConformEnergySpectrumView : public MeasureAnalysisView
{
class AntiConformEnergySpectrumView : public MeasureAnalysisView {
Q_OBJECT
public:
explicit AntiConformEnergySpectrumView(QWidget *parent = nullptr);
explicit AntiConformEnergySpectrumView(QWidget* parent = nullptr);
virtual ~AntiConformEnergySpectrumView();
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) override;
@ -20,9 +20,14 @@ protected:
virtual void showEvent(QShowEvent* e) override final;
private:
void loadAndProcess(); // 读取CSV执行符合处理绘制能谱折线图
void setupMenu();
void loadAndProcess(); // 读取CSV执行符合处理绘制能谱折线图
private slots:
void onActionPlotConfigure();
private:
QMenu* _menu = nullptr;
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot* _plot = nullptr;
QwtPlotCurve* _curve = nullptr;
@ -30,5 +35,3 @@ private:
};
#endif // ANTICONFORMENERGYSPECTRUMVIEW_H

View File

@ -14,6 +14,8 @@
#include <algorithm>
#include <cstdint>
#include <QPen>
#include <QMenu>
struct SpectrumData
{
int board_id;
@ -28,6 +30,9 @@ ConformToTheEnergySpectrum::ConformToTheEnergySpectrum(QWidget *parent) :
{
this->setViewType(PlotFrame);
this->_menu = new QMenu(this);
setupMenu();
_plot = new CustomQwtPlot();
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(_plot);
@ -50,6 +55,7 @@ ConformToTheEnergySpectrum::ConformToTheEnergySpectrum(QWidget *parent) :
_plot->enableAxis(QwtPlot::xBottom);
_plot->enableAxis(QwtPlot::yLeft);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
_curve = new QwtPlotCurve();
_curve->setStyle(QwtPlotCurve::Lines);
@ -154,9 +160,8 @@ void ConformToTheEnergySpectrum::loadAndProcess()
QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() {
_curve->setSamples(vx, vy);
_plot->setAxisScale(QwtPlot::xBottom, 0, dmaxx);
_plot->setAxisScale(QwtPlot::yLeft, 0, dmaxy * 1.1);
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, dmaxx);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, dmaxy);
_plot->replot();
_busy_indicator->Stop();
}, Qt::QueuedConnection);
@ -166,6 +171,11 @@ void ConformToTheEnergySpectrum::loadAndProcess()
load_thread->start();
}
void ConformToTheEnergySpectrum::onActionPlotConfigure()
{
}
void ConformToTheEnergySpectrum::showEvent(QShowEvent *e)
{
Q_UNUSED(e);
@ -175,4 +185,22 @@ void ConformToTheEnergySpectrum::showEvent(QShowEvent *e)
}
}
void ConformToTheEnergySpectrum::setupMenu()
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &ConformToTheEnergySpectrum::customContextMenuRequested, [this](const QPoint& pos) {
this->_menu->exec(this->mapToGlobal(pos));
});
QAction* action_plot_reset = this->_menu->addAction(QStringLiteral(u"还原"));
action_plot_reset->setObjectName("plot_reset");
connect(action_plot_reset, &QAction::triggered, [this]() {
this->_plot->ResetPlot();
});
this->_menu->addSeparator();
QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置"));
action_plot_config->setObjectName("plot_config");
connect(action_plot_config, &QAction::triggered, this, &ConformToTheEnergySpectrum::onActionPlotConfigure);
}

View File

@ -3,6 +3,7 @@
#include "MeasureAnalysisView.h"
class QMenu;
class CustomQwtPlot;
class QwtPlotCurve;
class BusyIndicator;
@ -20,9 +21,14 @@ protected:
virtual void showEvent(QShowEvent* e) override final;
private:
void setupMenu();
void loadAndProcess(); // 读取CSV执行符合处理绘制能谱折线图
private slots:
void onActionPlotConfigure();
private:
QMenu* _menu = nullptr;
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot* _plot = nullptr;
QwtPlotCurve* _curve = nullptr;

View File

@ -17,6 +17,7 @@
#include "csv.h"
#include <QThread>
#include "BusyIndicator.h"
#include <QMenu>
CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
MeasureAnalysisView(parent),
@ -25,9 +26,11 @@ CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
ui->setupUi(this);
this->setViewType(PlotFrame);
InitUi();
this->_menu = new QMenu(this);
_busy_indicator = new BusyIndicator(this);
InitUi();
setupMenu();
}
CountRateAnalysisView::~CountRateAnalysisView()
@ -82,20 +85,26 @@ void CountRateAnalysisView::setData(QVector<ParticleInjectTime> data)
QVector<double> vec(nVecSize); // 默认初始化为0
double minValue = 0;
double maxValue = 0;
for(auto info : data)
{
double x_max = 0;
double y_max = 0;
for(auto info : data) {
const qint64 ns = (info.dTime * 5) / NS_PER_SECOND;
const int nidx = static_cast<int>(ns / nInv); // 整数除法,速度快
if (nidx < nVecSize)
++vec[nidx]; // 使用 ++ 而非 vec[nidx]++
if (nidx < nVecSize) {
++vec[nidx]; // 使用 ++ 而非 vec[nidx]++
if ( y_max < vec[nidx] )
y_max = vec[nidx];
}
}
QVector<double> vecXpt(vec.size());
for (int i = 0; i < vec.size(); ++i)
for (int i = 0; i < vec.size(); ++i) {
vecXpt[i] = static_cast<double>(i);
if ( x_max < vecXpt[i] )
x_max = vecXpt[i];
}
plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max);
plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
// 创建曲线并设置数据
QwtPlotCurve *curve = new QwtPlotCurve();
curve->setSamples(vecXpt, vec);
@ -170,3 +179,26 @@ void CountRateAnalysisView::setupPlot()
plot->SetAxisDragScale(QwtPlot::xBottom, true);
}
void CountRateAnalysisView::setupMenu()
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &CountRateAnalysisView::customContextMenuRequested, [this](const QPoint& pos) {
this->_menu->exec(this->mapToGlobal(pos));
});
QAction* action_plot_reset = this->_menu->addAction(QStringLiteral(u"还原"));
action_plot_reset->setObjectName("plot_reset");
connect(action_plot_reset, &QAction::triggered, [this]() {
this->plot->ResetPlot();
});
this->_menu->addSeparator();
QAction* action_plot_config = this->_menu->addAction(QStringLiteral(u"图表配置"));
action_plot_config->setObjectName("plot_config");
connect(action_plot_config, &QAction::triggered, this, &CountRateAnalysisView::onActionPlotConfigure);
}
void CountRateAnalysisView::onActionPlotConfigure()
{
}

View File

@ -8,7 +8,7 @@
class CustomQwtPlot;
class BusyIndicator;
class QMenu;
namespace Ui {
class CountRateAnalysisView;
@ -34,11 +34,16 @@ protected:
private:
void InitUi();
void setupPlot();
void setupMenu();
private slots:
void onActionPlotConfigure();
private:
Ui::CountRateAnalysisView *ui;
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot *plot;
QMenu* _menu = nullptr;
QVector<ParticleInjectTime> m_AllData;//存储的所有的粒子入射时间数据
};

View File

@ -189,6 +189,7 @@ void EnergyCountPeakFitView::setupPlot()
legend->setDefaultItemMode(QwtLegendData::ReadOnly);
_plot->insertLegend(legend, QwtPlot::RightLegend);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
QwtPlotCurve *dummyFit = new QwtPlotCurve(QStringLiteral(u"拟合数据"));
dummyFit->setPen(QPen(Qt::blue, 2));
@ -269,10 +270,18 @@ void EnergyCountPeakFitView::loadDataFromFile(const QString& data_name, const QS
double energy;
unsigned long long energy_count;
QVector<double> x, y;
double x_max = 0.0f, y_max = 0.0f;
while (reader.read_row(energy, energy_count)) {
x.push_back(energy);
y.push_back(energy_count);
if ( x_max < energy )
x_max = energy;
if ( y_max < energy_count )
y_max = energy_count;
}
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
// 绘制曲线
QwtPlotCurve* curve = new QwtPlotCurve(QStringLiteral(u"原始数据"));
curve->setPen(QPen(Qt::gray, 2)); // 原始数据统一灰色

View File

@ -83,6 +83,8 @@ void EnergyCountPlotView::setupPlot()
_plot->insertLegend(legend, QwtPlot::RightLegend);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
_data_selector = new CustomQwtPlotXaxisSelector(_plot->canvas());
_data_selector->setEnabled(false);
}
@ -127,7 +129,14 @@ void EnergyCountPlotView::loadDataFromFile(const QString &data_name, const QStri
while (reader.read_row(energy, energy_count)) {
x.push_back(energy);
y.push_back(energy_count);
if ( _x_max < energy )
_x_max = energy;
if ( _y_max < energy_count )
_y_max = energy_count;
}
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, _x_max);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, _y_max);
// 绘制曲线
QwtPlotCurve* curve = new QwtPlotCurve(data_name);
curve->setSamples(x, y);

View File

@ -34,6 +34,8 @@ private:
QMenu* _menu = nullptr;
QDialog* _curve_show_setting_dlg = nullptr;
CustomQwtPlotXaxisSelector* _data_selector = nullptr;
double _x_max = 0.0f;
double _y_max = 0.0f;
};
#endif // ENERGYCOUNTPLOTVIEW_H

View File

@ -1,191 +1,220 @@
#include "MeasureClient.h"
#include "MeasureServiceProtocol.h"
#include <QByteArray>
#include <QTimer>
#include <QJsonDocument>
#include <QDataStream>
#include <QDebug>
MeasureClient::MeasureClient(QObject *parent) : QObject(parent)
MeasureClient::MeasureClient(QObject *parent)
: QObject(parent),
_is_auto_reconnect(true),
_response_buffer(new QByteArray()),
_response_data_len(0)
{
_host = "127.0.0.1";
_port = 9999;
// 创建工作线程
_workerThread = new QThread(this);
this->moveToThread(_workerThread);
_workerThread->start();
_tcp_socket = new QTcpSocket(this);
_reconnect_timer = new QTimer(this);
connect(_tcp_socket, &QTcpSocket::connected, this, &MeasureClient::onConnected);
connect(_tcp_socket, &QTcpSocket::disconnected, this, &MeasureClient::onDisconnected);
connect(_tcp_socket, &QTcpSocket::readyRead, this, &MeasureClient::onReadyRead);
connect(_tcp_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &MeasureClient::onSocketError);
connect(_reconnect_timer, &QTimer::timeout, this, &MeasureClient::tryReconnect);
_reconnect_timer->setInterval(300);
}
MeasureClient::~MeasureClient()
{
if (_workerThread->isRunning()) {
_workerThread->quit();
_workerThread->wait();
if (_tcp_socket->isOpen()) {
_tcp_socket->close();
}
delete _workerThread;
}
void MeasureClient::setServerAddress(const QString &host, quint16 port)
void MeasureClient::connectToServer(const QString &ip, quint16 port)
{
QMutexLocker locker(&_mutex);
_host = host;
_host = ip;
_port = port;
_tcp_socket->connectToHost(_host, _port);
}
void MeasureClient::startMeasure(const QString &deviceGuid, const QVariantMap &config)
void MeasureClient::disconnectFromServer()
{
QMetaObject::invokeMethod(this, "processCommand", Qt::QueuedConnection,
Q_ARG(QString, "START"),
Q_ARG(QString, deviceGuid),
Q_ARG(QVariantMap, config));
_is_auto_reconnect = false;
_reconnect_timer->stop();
if (_tcp_socket->isOpen()) {
_tcp_socket->disconnectFromHost();
_tcp_socket->close();
}
}
void MeasureClient::stopMeasure(const QString &deviceGuid)
{
QMetaObject::invokeMethod(this, "processCommand", Qt::QueuedConnection,
Q_ARG(QString, "STOP"),
Q_ARG(QString, deviceGuid),
Q_ARG(QVariantMap, QVariantMap()));
}
void MeasureClient::setMeasureConfigParams(const QString &deviceGuid, const QVariantMap &config)
{
QMetaObject::invokeMethod(this, "processCommand", Qt::QueuedConnection,
Q_ARG(QString, "SET"),
Q_ARG(QString, deviceGuid),
Q_ARG(QVariantMap, config));
}
void MeasureClient::clearData(const QString &deviceGuid)
{
QMetaObject::invokeMethod(this, "processCommand", Qt::QueuedConnection,
Q_ARG(QString, "CLEAR"),
Q_ARG(QString, deviceGuid),
Q_ARG(QVariantMap, QVariantMap()));
}
void MeasureClient::getDeviceList()
{
QMetaObject::invokeMethod(this, "processCommand", Qt::QueuedConnection,
Q_ARG(QString, "DEVICE"),
Q_ARG(QString, ""),
Q_ARG(QVariantMap, QVariantMap()));
}
void MeasureClient::processCommand(const QString &command, const QString &device_guid, const QVariantMap &config)
void MeasureClient::startMeasure(const QString &device_guid, const QVariantMap &config)
{
QString data;
if (!config.isEmpty()) {
QJsonDocument json_doc = QJsonDocument::fromVariant(config);
data = json_doc.toJson(QJsonDocument::Compact);
}
QVariantMap response = sendCommand(command, device_guid, data);
bool success = response["success"].toBool();
QString message = response["message"].toString();
if (command == "START") {
QString gvf_filename;
if (success) {
gvf_filename = response["devices"].toString();
emit startMeasureResult(success, gvf_filename);
} else {
emit startMeasureResult(success, message);
}
} else if (command == "STOP") {
emit stopMeasureResult(success, message);
} else if (command == "SET") {
emit setMeasureConfigParamsResult(success, message);
} else if (command == "CLEAR") {
emit clearDataResult(success, message);
} else if (command == "DEVICE") {
QStringList devices;
if (success) {
devices = response["devices"].toStringList();
}
emit getDeviceListResult(success, devices);
} else {
emit errorOccurred(message);
}
}
QVariantMap MeasureClient::sendCommand(const QString &command, const QString &device_guid, const QString &data)
{
QVariantMap result;
result["success"] = false;
QMutexLocker locker(&_mutex);
QString host = _host;
quint16 port = _port;
locker.unlock();
// 创建临时socket短连接
QTcpSocket socket;
socket.connectToHost(host, port);
if (!socket.waitForConnected(3000)) {
result["message"] = QStringLiteral(u"连接服务失败:") + socket.errorString();
emit errorOccurred(result["message"].toString());
return result;
}
// 发送命令
QByteArray request_data;
QDataStream request_stream(&request_data, QIODevice::WriteOnly);
request_stream << command << device_guid;
request_stream << QString("START") << device_guid;
if (!data.isEmpty()) {
request_stream << data;
}
socket.write(request_data);
if (!socket.waitForBytesWritten(1000)) {
result["message"] = QStringLiteral(u"发送请求失败:") + socket.errorString();
emit errorOccurred(result["message"].toString());
socket.disconnectFromHost();
return result;
this->sendRequst(request_data);
}
void MeasureClient::stopMeasure(const QString &device_guid)
{
QByteArray request_data;
QDataStream request_stream(&request_data, QIODevice::WriteOnly);
request_stream << QString("STOP") << device_guid;
this->sendRequst(request_data);
}
void MeasureClient::setMeasureConfigParams(const QString &device_guid, const QVariantMap &config)
{
QByteArray request_data;
QDataStream request_stream(&request_data, QIODevice::WriteOnly);
request_stream << QString("SET") << device_guid;
this->sendRequst(request_data);
}
void MeasureClient::clearData(const QString &device_guid)
{
QByteArray request_data;
QDataStream request_stream(&request_data, QIODevice::WriteOnly);
request_stream << QString("CLEAR") << device_guid;
this->sendRequst(request_data);
}
void MeasureClient::getDeviceList()
{
QByteArray request_data;
QDataStream request_stream(&request_data, QIODevice::WriteOnly);
request_stream << QString("DEVICE");
this->sendRequst(request_data);
}
void MeasureClient::onConnected()
{
_reconnect_timer->stop();
emit runningInfo(QStringLiteral(u"连接到服务器"));
}
void MeasureClient::onDisconnected()
{
if (_is_auto_reconnect) {
emit runningInfo(QStringLiteral(u"重连服务器......"));
_reconnect_timer->start();
} else {
emit runningInfo(QStringLiteral(u"断开服务器连接"));
}
// 等待响应
if (!socket.waitForReadyRead(5000)) {
result["message"] = QStringLiteral(u"服务无响应:") + socket.errorString();
emit errorOccurred(result["message"].toString());
socket.disconnectFromHost();
return result;
}
void MeasureClient::onReadyRead()
{
_response_buffer->append(_tcp_socket->readAll());
while (true) {
if (_response_data_len == 0) {
if (_response_buffer->size() < Protocol::HEAD_SIZE) break;
QByteArray head = _response_buffer->left(Protocol::HEAD_SIZE);
_response_data_len = Protocol::UnpackDataLen(head);
_response_buffer->remove(0, Protocol::HEAD_SIZE);
}
if (_response_buffer->size() >= _response_data_len) {
QByteArray response_data = _response_buffer->left(_response_data_len);
_response_buffer->remove(0, _response_data_len);
QThread* process_thread = QThread::create(&MeasureClient::processResponse, this, response_data);
connect(process_thread, &QThread::finished, process_thread, &QThread::deleteLater);
process_thread->start();
_response_data_len = 0;
} else {
break;
}
}
// 读取响应
QByteArray response_data = socket.readAll();
QDataStream response_stream(&response_data, QIODevice::ReadOnly);
}
void MeasureClient::onSocketError(QAbstractSocket::SocketError error)
{
emit errorOccurred(QStringLiteral(u"连接异常:%1").arg(_tcp_socket->errorString()));
if (error == QAbstractSocket::ConnectionRefusedError) {
_reconnect_timer->start();
}
}
void MeasureClient::tryReconnect()
{
_tcp_socket->connectToHost(_host, _port);
}
void MeasureClient::sendRequst(const QByteArray &data)
{
if (!_tcp_socket->isOpen()) {
emit errorOccurred(QStringLiteral(u"未连接服务器,请求发送失败"));
return;
}
QByteArray requst_buf = Protocol::PackData(data);
_tcp_socket->write(requst_buf);
_tcp_socket->flush();
}
void MeasureClient::processResponse(const QByteArray &response_data)
{
QDataStream response_stream(response_data);
QString response_command;
bool success;
response_stream >> response_command >> success;
result["success"] = success;
if (response_command == "DEVICE") {
// 处理设备列表响应
if (response_command == "GVF") {
int data_size;
response_stream >> data_size;
QByteArray data_buf;
data_buf.resize(data_size);
response_stream.readRawData(data_buf.data(), data_size);
emit gvfData(data_buf);
} else if (response_command == "START") {
if (success) {
QString measure_gvf_data_filename;
response_stream >> measure_gvf_data_filename;
emit startMeasureResult(success, measure_gvf_data_filename);
} else {
QString message;
response_stream >> message;
emit startMeasureResult(success, message);
}
} else if (response_command == "DEVICE") {
QStringList devices;
QString message;
if (success) {
int count;
response_stream >> count;
QStringList devices;
for (int i = 0; i < count; ++i) {
QString device;
response_stream >> device;
devices << device;
}
result["devices"] = devices;
} else {
response_stream >> message;
}
} else if ((response_command == "START") && success) {
// 处理设备列表响应
if (success) {
QString measure_gvf_data_filename;
response_stream >> measure_gvf_data_filename;
result["gvf"] = measure_gvf_data_filename;
}
} else {
// 处理其他响应
emit getDeviceListResult(success, message, devices);
} else if (response_command == "STOP") {
QString message;
response_stream >> message;
result["message"] = message;
emit stopMeasureResult(success, message);
} else if (response_command == "SET") {
QString message;
response_stream >> message;
emit setMeasureConfigParamsResult(success, message);
} else if (response_command == "CLEAR") {
QString message;
response_stream >> message;
emit clearDataResult(success, message);
} else {
QString message;
response_stream >> message;
emit errorOccurred(message);
}
// 断开连接
socket.disconnectFromHost();
if (socket.state() != QTcpSocket::UnconnectedState) {
socket.waitForDisconnected(1000);
}
return result;
}

View File

@ -2,14 +2,13 @@
#define MEASURECLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QDataStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QVariantMap>
#include <QVariantList>
#include <QThread>
#include <QMutex>
#include <QTcpSocket>
class QByteArray;
class QTimer;
class MeasureClient : public QObject
{
@ -19,42 +18,45 @@ public:
explicit MeasureClient(QObject *parent = nullptr);
~MeasureClient();
// 设置服务器地址和端口
void setServerAddress(const QString &host, quint16 port);
// 启动测量(异步)
void startMeasure(const QString &deviceGuid, const QVariantMap &config);
// 停止测量(异步)
void stopMeasure(const QString &deviceGuid);
// 设置测量参数(异步)
void setMeasureConfigParams(const QString &deviceGuid, const QVariantMap &config);
// 清除数据(异步)
void clearData(const QString &deviceGuid);
// 获取设备列表(异步)
void connectToServer(const QString &ip = "127.0.0.1", quint16 port = 9999);
void disconnectFromServer();
void startMeasure(const QString &device_guid, const QVariantMap &config);
void stopMeasure(const QString &device_guid);
void setMeasureConfigParams(const QString &device_guid, const QVariantMap &config);
void clearData(const QString &device_guid);
void getDeviceList();
signals:
// 操作结果信号
void startMeasureResult(bool success, const QString &info);
void stopMeasureResult(bool success, const QString &message);
void setMeasureConfigParamsResult(bool success, const QString &message);
void clearDataResult(bool success, const QString &message);
void getDeviceListResult(bool success, const QStringList &devices);
// 错误信号
void errorOccurred(const QString &errorString);
void getDeviceListResult(bool success, const QString &message, const QStringList &devices);
void runningInfo(const QString &info);
void errorOccurred(const QString &error);
void gvfData(const QByteArray& data);
private slots:
// 处理命令执行
void processCommand(const QString &command, const QString &device_guid, const QVariantMap &config);
void onConnected();
void onDisconnected();
void onReadyRead();
void onSocketError(QAbstractSocket::SocketError error);
void tryReconnect();
private:
// 发送命令并获取响应(短连接模式)
QVariantMap sendCommand(const QString &command, const QString &device_guid, const QString &data = QString());
void sendRequst(const QByteArray &data);
void processResponse(const QByteArray &response_data);
private:
QMutex _mutex;
QString _host;
quint16 _port;
QThread *_workerThread;
QMutex _mutex;
QTcpSocket *_tcp_socket;
QTimer *_reconnect_timer;
bool _is_auto_reconnect;
QByteArray *_response_buffer;
qint32 _response_data_len;
};
#endif // MEASURECLIENT_H

View File

@ -2,9 +2,8 @@ INCLUDEPATH += $${PWD}
DEPENDPATH += $${PWD}
SOURCES += \
$$PWD/MeasureClient.cpp \
$$PWD/MeasureWorker.cpp
$$PWD/MeasureClient.cpp
HEADERS += \
$$PWD/MeasureClient.h \
$$PWD/MeasureWorker.h
$$PWD/MeasureServiceProtocol.h

View File

@ -0,0 +1,34 @@
#ifndef MEASURESERVICEPROTOCOL_H
#define MEASURESERVICEPROTOCOL_H
#include <QByteArray>
namespace Protocol {
// 固定协议头长度8字节
const int HEAD_SIZE = 8;
// 打包数据:添加长度头
inline QByteArray PackData(const QByteArray &data) {
QByteArray buffer;
buffer.resize(HEAD_SIZE);
// 前4字节 = 数据总长度
qint32 data_len = data.size();
memcpy(buffer.data(), &data_len, 4);
// 后4字节保留
qint32 reserve = 0xFFFFFFFF;
memcpy(buffer.data() + 4, &reserve, 4);
buffer.append(data);
return buffer;
}
// 解包:从头部获取数据长度
inline qint32 UnpackDataLen(const QByteArray &head) {
if (head.size() < HEAD_SIZE)
return 0;
qint32 len = 0;
memcpy(&len, head.constData(), 4);
return len;
}
}
#endif // MEASURESERVICEPROTOCOL_H

View File

@ -1,165 +0,0 @@
#include "MeasureWorker.h"
#include "MeasureClient.h"
#include <QDir>
#include "GlobalDefine.h"
#include "MeasureAnalysisProjectModel.h"
MeasureWorker* MeasureWorker::_s_instance { nullptr };
MeasureWorker::MeasureWorker(QObject* parent)
: QObject(parent)
{
_measure_client = new MeasureClient;
connect(_measure_client, &MeasureClient::getDeviceListResult, this, &MeasureWorker::onGetDeviceListResult);
connect(_measure_client, &MeasureClient::startMeasureResult, this, &MeasureWorker::onStartMeasureResult);
connect(_measure_client, &MeasureClient::stopMeasureResult, this, &MeasureWorker::onStopMeasureResult);
connect(_measure_client, &MeasureClient::setMeasureConfigParamsResult, this, &MeasureWorker::onSetMeasureConfigParamsResult);
connect(_measure_client, &MeasureClient::clearDataResult, this, &MeasureWorker::onClearDataResult);
connect(_measure_client, &MeasureClient::errorOccurred, this, &MeasureWorker::onErrorOccurred);
}
MeasureWorker *MeasureWorker::Instance()
{
if (!_s_instance) {
_s_instance = new MeasureWorker();
}
return _s_instance;
}
MeasureWorker::~MeasureWorker()
{
delete _measure_client;
}
void MeasureWorker::SetMeasureProjectName(const QString &project_name)
{
_measure_project_name = project_name;
}
void MeasureWorker::Connect()
{
LOG_INFO(QStringLiteral(u"查找测量设备... ..."));
_measure_client->getDeviceList();
}
void MeasureWorker::Start()
{
auto project_model = ProjectList::Instance()->GetProjectModel(_measure_project_name);
if (!project_model) {
return;
}
const QString& device_guid = project_model->GetDeviceGuid();
if (device_guid.isEmpty()) {
LOG_WARN(QStringLiteral(u"未选择测量设备GUID."));
return;
}
const QString& config_filename = project_model->GetMeasureDeviceParamsCfgFilename();
QFile json_file(config_filename);
if (!json_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LOG_WARN(QStringLiteral(u"加载设备参数配置失败:%1").arg(config_filename));
return;
}
QByteArray json_data = json_file.readAll();
json_file.close();
QJsonDocument json_doc = QJsonDocument::fromJson(json_data);
if (json_doc.isNull()) {
return;
}
if (!json_doc.isObject())
return;
QVariantMap device_config_info = json_doc.object().toVariantMap();
if (!device_config_info.contains(QStringLiteral(u"ChannelConfig")))
return;
QVariantList channel_config_list = device_config_info[QStringLiteral(u"ChannelConfig")].toList();
if (channel_config_list.isEmpty()) {
LOG_WARN(QStringLiteral(u"测量设备通道配置参数为空."));
return;
}
LOG_INFO(QStringLiteral(u"开始测量... ..."));
_measure_client->startMeasure(device_guid, device_config_info);
}
void MeasureWorker::Stop()
{
auto project_model = ProjectList::Instance()->GetProjectModel(_measure_project_name);
if (!project_model) {
return;
}
const QString& device_guid = project_model->GetDeviceGuid();
if (device_guid.isEmpty()) {
LOG_WARN(QStringLiteral(u"未选择测量设备GUID."));
return;
}
LOG_INFO(QStringLiteral(u"停止测量... ..."));
_measure_client->stopMeasure(device_guid);
}
void MeasureWorker::ClearData()
{
auto project_model = ProjectList::Instance()->GetProjectModel(_measure_project_name);
if (!project_model) {
return;
}
const QString& device_guid = project_model->GetDeviceGuid();
if (device_guid.isEmpty()) {
LOG_WARN(QStringLiteral(u"未选择测量设备GUID."));
return;
}
LOG_INFO(QStringLiteral(u"清除测量数据... ..."));
_measure_client->clearData(device_guid);
}
void MeasureWorker::onStartMeasureResult(bool success, const QString &info)
{
if (success) {
LOG_INFO(QStringLiteral(u"启动测量成功"));
LOG_INFO(QStringLiteral(u"测量数据GVF文件: %1").arg(info));
} else {
LOG_WARN(QStringLiteral(u"启动测量失败: %1").arg(info));
}
}
void MeasureWorker::onStopMeasureResult(bool success, const QString &message)
{
if (success) {
LOG_INFO(QStringLiteral(u"停止测量成功"));
} else {
LOG_WARN(QStringLiteral(u"停止测量失败: %1").arg(message));
}
}
void MeasureWorker::onSetMeasureConfigParamsResult(bool success, const QString &message)
{
if (success) {
LOG_INFO(QStringLiteral(u"设置测量参数成功"));
} else {
LOG_WARN(QStringLiteral(u"设置测量参数失败: %1").arg(message));
}
}
void MeasureWorker::onClearDataResult(bool success, const QString &message)
{
if (success) {
LOG_INFO(QStringLiteral(u"清除测量数据成功"));
} else {
LOG_WARN(QStringLiteral(u"清除测量数据失败: %1").arg(message));
}
}
void MeasureWorker::onGetDeviceListResult(bool success, const QStringList &devices)
{
if (success && !devices.isEmpty()) {
LOG_INFO(QStringLiteral(u"获取测量设备GUID成功:%1").arg(devices.first()));
auto project_model = ProjectList::Instance()->GetProjectModel(_measure_project_name);
if (project_model) {
project_model->SetDeviceGuid(devices.first());
}
} else {
LOG_WARN(QStringLiteral(u"获取测量设备失败"));
}
}
void MeasureWorker::onErrorOccurred(const QString &errorString)
{
LOG_WARN(QStringLiteral(u"错误: %1").arg(errorString));
}

View File

@ -1,42 +0,0 @@
#ifndef MEASUREWORKER_H
#define MEASUREWORKER_H
#include <QObject>
class MeasureClient;
class MeasureWorker : public QObject
{
Q_OBJECT
private:
MeasureWorker(QObject* parent = nullptr);
static MeasureWorker* _s_instance;
public:
static MeasureWorker* Instance();
virtual ~MeasureWorker();
void SetMeasureProjectName(const QString& project_name);
void Connect();
void Start();
void Stop();
void ClearData();
private slots:
void onStartMeasureResult(bool success, const QString& info);
void onStopMeasureResult(bool success, const QString& message);
void onSetMeasureConfigParamsResult(bool success, const QString& message);
void onClearDataResult(bool success, const QString& message);
void onGetDeviceListResult(bool success, const QStringList &devices);
void onErrorOccurred(const QString &errorString);
private:
MeasureClient* _measure_client = nullptr;
QString _measure_project_name;
};
#endif

View File

@ -48,7 +48,6 @@ ParticleCountPlotView::ParticleCountPlotView(QWidget* parent)
ParticleCountPlotView::~ParticleCountPlotView()
{
LOG_DEBUG(QStringLiteral(u"%1析构.").arg(this->GetViewName()));
}
void ParticleCountPlotView::InitViewWorkspace(const QString& project_name)
@ -178,8 +177,11 @@ void ParticleCountPlotView::setupPlot()
_plot->insertLegend(legend, QwtPlot::RightLegend);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
// new CustomQwtPlotXaxisPanner(_plot->canvas());
// new CustomQwtPlotXaxisMagnifier(_plot->canvas());
_data_selector = new CustomQwtPlotXaxisSelector(_plot->canvas());
_data_selector->setEnabled(false);
}
@ -222,11 +224,16 @@ void ParticleCountPlotView::loadDataFromFile(const QString& data_name, const QSt
int address;
unsigned long long particle_count;
QVector<double> x, y;
while (reader.read_row(address, particle_count)) {
x.push_back(address);
y.push_back(particle_count);
if ( _x_max < address )
_x_max = address;
if ( _y_max < particle_count )
_y_max = particle_count;
}
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, _x_max);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, _y_max);
// 绘制曲线
QwtPlotCurve* curve = new QwtPlotCurve(data_name);

View File

@ -56,6 +56,8 @@ private:
FindPeaksResultDialog* _find_peaks_result_dlg = nullptr;
CustomQwtPlotXaxisSelector* _data_selector = nullptr;
BatchEnergyScaleDialog* _batch_energy_scale_dlg = nullptr;
double _x_max = 0.0f;
double _y_max = 0.0f;
};
#endif // PARTICLECOUNTPLOTVIEW_H

View File

@ -48,6 +48,7 @@ ParticleInjectTimeAnalysisView::ParticleInjectTimeAnalysisView(QWidget *parent)
_plot->enableAxis(QwtPlot::yLeft);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_plot->SetAxisDragScale(QwtPlot::yLeft, true);
// // 设置QWT图例
// QwtLegend* legend = new QwtLegend();
@ -123,6 +124,7 @@ void ParticleInjectTimeAnalysisView::updateData(bool b_init_update)
int board, channel;
double energy;
unsigned long long time_count;
double x_max = 0.0f, y_max = 0.0f;
while (in.read_row(board, channel, energy, time_count)) {
if ( !b_init_update && (energy <= _begin_enery || energy >= _end_energy)) {
continue;
@ -130,7 +132,13 @@ void ParticleInjectTimeAnalysisView::updateData(bool b_init_update)
particle_num++;
x.append(particle_num);
y.append(time_count);
if ( x_max < particle_num )
x_max = particle_num;
if ( y_max < time_count )
y_max = time_count;
}
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
_curve->setSamples(x, y);
_plot->replot();
LOG_INFO(QStringLiteral(u"%1数据更新完毕.").arg(this->GetViewName()));

View File

@ -157,7 +157,7 @@ void ParticleTimeDifferenceView::loadDataFromFile()
y_max = count;
}
_histogram->setData(new QwtIntervalSeriesData(samples));
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, _x_max);
_plot->SetAxisInitRange(QwtPlot::xBottom, 0.0f, x_max);
_plot->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
_plot->replot();
const QString& info = QStringLiteral(u"粒子时间差分析处理完成.");