优化加载动画

This commit is contained in:
徐海 2026-05-13 11:29:36 +08:00
parent d0be9a8654
commit 814b85d40b
8 changed files with 122 additions and 109 deletions

View File

@ -68,12 +68,14 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
QString csvFile = data_files_set.first().toString(); QString csvFile = data_files_set.first().toString();
if (csvFile.isEmpty()) if (csvFile.isEmpty())
return; return;
auto functionToRun = [this, csvFile]() {
_busy_indicator->Start(); _busy_indicator->Start();
auto functionToRun = [this, csvFile]() {
readCsv(csvFile); readCsv(csvFile);
generateSurfaceData(); generateSurfaceData();
QMetaObject::invokeMethod(this, [this]() {
updateSpectrogram(); updateSpectrogram();
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
}; };
QThread* load_data_thread = QThread::create(functionToRun); QThread* load_data_thread = QThread::create(functionToRun);
load_data_thread->start(); load_data_thread->start();

View File

@ -83,11 +83,14 @@ void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, Q
void AntiConformEnergySpectrumView::loadAndProcess() void AntiConformEnergySpectrumView::loadAndProcess()
{ {
auto functionToRun = [this]() {
if (_data_filename.isEmpty())
return;
_busy_indicator->Start(); _busy_indicator->Start();
auto functionToRun = [this]() {
if (_data_filename.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop();
}, Qt::QueuedConnection);
return;
}
std::vector<SpectrumData> rawData; std::vector<SpectrumData> rawData;
io::CSVReader<4> in(QStrToSysPath(_data_filename)); io::CSVReader<4> in(QStrToSysPath(_data_filename));
@ -110,7 +113,9 @@ void AntiConformEnergySpectrumView::loadAndProcess()
} }
if (rawData.empty()) { if (rawData.empty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
return; return;
} }
@ -129,7 +134,9 @@ void AntiConformEnergySpectrumView::loadAndProcess()
} }
if (vx.isEmpty()) { if (vx.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
return; return;
} }

View File

@ -89,13 +89,15 @@ void CoincidenceEventTimeView::SetAnalyzeDataFilename(const QMap<QString, QVaria
void CoincidenceEventTimeView::loadAndProcess() void CoincidenceEventTimeView::loadAndProcess()
{ {
auto functionToRun = [this]() {
if (_data_filenames.isEmpty()) return;
_busy_indicator->Start(); _busy_indicator->Start();
auto functionToRun = [this]() {
if (_data_filenames.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop();
}, Qt::QueuedConnection);
return;
}
std::vector<SpectrumData> rawData; std::vector<SpectrumData> rawData;
for (const QString& filename : _data_filenames) { for (const QString& filename : _data_filenames) {
io::CSVReader<5> in(QStrToSysPath(filename)); io::CSVReader<5> in(QStrToSysPath(filename));
in.read_header(io::ignore_extra_column, in.read_header(io::ignore_extra_column,
@ -126,17 +128,15 @@ void CoincidenceEventTimeView::loadAndProcess()
}); });
} }
if (rawData.empty()) { if (rawData.empty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
return; return;
} }
int eventId = 0; int eventId = 0;
QList<SpectrumData> SpectrumDataList; QList<SpectrumData> SpectrumDataList;
for (const auto& spdt : rawData) for (const auto& spdt : rawData) {
{
// 第一个事件是初级粒子 // 第一个事件是初级粒子
const auto& firstParticle = spdt; const auto& firstParticle = spdt;
int boardId = firstParticle.board_id + 1; int boardId = firstParticle.board_id + 1;
@ -150,15 +150,16 @@ void CoincidenceEventTimeView::loadAndProcess()
QVector<double> vx, vy; QVector<double> vx, vy;
int ncount = 0; int ncount = 0;
for(const auto &spdt : SpectrumDataList) for(const auto &spdt : SpectrumDataList) {
{
ncount++; ncount++;
vx << spdt.timestamp; vx << spdt.timestamp;
vy << ncount; vy << ncount;
} }
if (vx.isEmpty()) { if (vx.isEmpty()) {
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
return; return;
} }

View File

@ -44,14 +44,14 @@ void CountRateAnalysisView::InitViewWorkspace(const QString &project_name)
} }
void CountRateAnalysisView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set) void CountRateAnalysisView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{ {
if(!data_files_set.isEmpty()) if(!data_files_set.isEmpty()) {
{
auto functionToRun = [this,data_files_set]
{
_busy_indicator->Start(); _busy_indicator->Start();
m_AllData = getParticleInjectTimeData(data_files_set.first().toString()); auto functionToRun = [this,data_files_set] {
setData(m_AllData); QVector<ParticleInjectTime> data = getParticleInjectTimeData(data_files_set.first().toString());
QMetaObject::invokeMethod(this, [this, data]() {
setData(data);
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
}; };
QThread* load_data_thread = QThread::create(functionToRun); QThread* load_data_thread = QThread::create(functionToRun);
load_data_thread->start(); load_data_thread->start();

View File

@ -44,7 +44,6 @@ private:
BusyIndicator* _busy_indicator = nullptr; BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot *plot; CustomQwtPlot *plot;
QMenu* _menu = nullptr; QMenu* _menu = nullptr;
QVector<ParticleInjectTime> m_AllData;//存储的所有的粒子入射时间数据
}; };
#endif //COUNTRATEANALYSIS_H #endif //COUNTRATEANALYSIS_H

View File

@ -1,24 +1,23 @@
#ifndef ENERGYCOUNTPEAKFITVIEW_H #ifndef ENERGYCOUNTPEAKFITVIEW_H
#define ENERGYCOUNTPEAKFITVIEW_H #define ENERGYCOUNTPEAKFITVIEW_H
#include <QObject> #include "PeakFitParamsDialog.h"
#include <QWidget>
#include <MeasureAnalysisView.h> #include <MeasureAnalysisView.h>
#include <QwtPlotPicker>
#include <QwtPickerDragRectMachine>
#include <QRubberBand> // 新增
#include <qwt_plot_shapeitem.h> // 新增
#include <QDateTime> #include <QDateTime>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonObject> #include <QJsonObject>
#include "PeakFitParamsDialog.h" #include <QObject>
#include <QRubberBand> // 新增
#include <QWidget>
#include <QwtPickerDragRectMachine>
#include <QwtPlotPicker>
#include <qwt_plot_shapeitem.h> // 新增
#include "DataCalcProcess/FindPeaksBySvd.h"
#include "DataCalcProcess/NolinearLeastSquaresCurveFit.h"
#include "DataCalcProcess/AdaptiveSimpsonIntegrate.h" #include "DataCalcProcess/AdaptiveSimpsonIntegrate.h"
#include "DataCalcProcess/FindPeaksBySvd.h"
#include "DataCalcProcess/MathModelDefine.h" #include "DataCalcProcess/MathModelDefine.h"
#include "DataCalcProcess/NolinearLeastSquaresCurveFit.h"
struct PeakFitResult struct PeakFitResult {
{
double center; // 峰中心能量 (keV) double center; // 峰中心能量 (keV)
double amplitude; // 高斯振幅 double amplitude; // 高斯振幅
double sigma; // 高斯宽度 double sigma; // 高斯宽度
@ -38,7 +37,7 @@ struct FitCurveData {
double center; // 峰中心 double center; // 峰中心
double xMin; // 曲线X范围最小值 double xMin; // 曲线X范围最小值
double xMax; // 曲线X范围最大值 double xMax; // 曲线X范围最大值
QRectF selectionRect; //关联的框选区域 QRectF selectionRect; // 关联的框选区域
double fwhm; // 半高宽 double fwhm; // 半高宽
double area; // 峰面积 double area; // 峰面积
@ -46,7 +45,7 @@ struct FitCurveData {
struct PeakFitHistoryItem { struct PeakFitHistoryItem {
QDateTime timestamp; QDateTime timestamp;
QList<FitCurveData> curveList; //存储多条曲线 QList<FitCurveData> curveList; // 存储多条曲线
QJsonObject toJson() const; QJsonObject toJson() const;
static PeakFitHistoryItem fromJson(const QJsonObject& obj); static PeakFitHistoryItem fromJson(const QJsonObject& obj);
@ -58,14 +57,17 @@ struct CurrentFitRecord {
double xMin; // X范围最小值 double xMin; // X范围最小值
double xMax; // X范围最大值 double xMax; // X范围最大值
int historyIndex; // 对应_fitHistoryList中的索引-1表示未保存 int historyIndex; // 对应_fitHistoryList中的索引-1表示未保存
CurrentFitRecord() : historyIndex(-1) {} // 构造函数初始化 CurrentFitRecord()
: historyIndex(-1)
{
} // 构造函数初始化
}; };
struct DisplayedCurveRef { struct DisplayedCurveRef {
int historyIndex; // 对应 _fitHistoryList 的索引 int historyIndex; // 对应 _fitHistoryList 的索引
int curveIndex; // 对应 curveList 的索引 int curveIndex; // 对应 curveList 的索引
int curveStartIndex; //对应 _fitCurves 中的起始索引一条历史曲线对应2条Qwt曲线拟合+本底) int curveStartIndex; // 对应 _fitCurves 中的起始索引一条历史曲线对应2条Qwt曲线拟合+本底)
int rectIndex; //对应 _selectionRectItems 中的索引 int rectIndex; // 对应 _selectionRectItems 中的索引
}; };
class PlotRectItem; // 前向声明 class PlotRectItem; // 前向声明
@ -76,11 +78,10 @@ class QwtPlotPicker;
class QwtPlotCurve; class QwtPlotCurve;
class BusyIndicator; class BusyIndicator;
class EnergyCountPeakFitView : public MeasureAnalysisView class EnergyCountPeakFitView : public MeasureAnalysisView {
{
Q_OBJECT Q_OBJECT
public: public:
EnergyCountPeakFitView(QWidget *parent = nullptr); EnergyCountPeakFitView(QWidget* parent = nullptr);
virtual ~EnergyCountPeakFitView(); virtual ~EnergyCountPeakFitView();
virtual void InitViewWorkspace(const QString& project_name) override final; virtual void InitViewWorkspace(const QString& project_name) override final;
@ -89,17 +90,16 @@ public:
private: private:
void setupPlot(); void setupPlot();
void setupMenu(); void setupMenu();
void loadDataFromFile(const QString &data_name, const QString& filename); void loadDataFromFile(const QString& data_name, const QString& filename);
void loadHistoryFromFile(); void loadHistoryFromFile();
void saveHistoryToFile(); void saveHistoryToFile();
void saveCurrentFitToHistory(); // 保存当前拟合结果 void saveCurrentFitToHistory(); // 保存当前拟合结果
void displayFitFromHistory(const PeakFitHistoryItem& item); // 显示历史拟合曲线 void displayFitFromHistory(const PeakFitHistoryItem& item); // 显示历史拟合曲线
//处理鼠标悬停检测 // 处理鼠标悬停检测
void updateHoverState(const QPoint& mousePos); void updateHoverState(const QPoint& mousePos);
//显示选中的曲线 // 显示选中的曲线
void displaySelectedCurves(const QList<FitCurveData>& curves, const QList<DisplayedCurveRef>& refs); void displaySelectedCurves(const QList<FitCurveData>& curves, const QList<DisplayedCurveRef>& refs);
private slots: private slots:
void onActionCurveShowSetting(); void onActionCurveShowSetting();
@ -109,8 +109,9 @@ private slots:
void onActionSaveCurrentFit(); void onActionSaveCurrentFit();
void onActionShowFitHistory(); void onActionShowFitHistory();
void onActionDeleteHoveredRect(); void onActionDeleteHoveredRect();
//重新拟合当前悬停的框选区域 // 重新拟合当前悬停的框选区域
void onActionRefitCurrentRect(); void onActionRefitCurrentRect();
protected: protected:
bool eventFilter(QObject* watched, QEvent* event) override; // 事件过滤器 bool eventFilter(QObject* watched, QEvent* event) override; // 事件过滤器
@ -121,7 +122,7 @@ private:
void addSelectionRect(const QRectF& plotRect); void addSelectionRect(const QRectF& plotRect);
void fadeSelectionRectBorders(); void fadeSelectionRectBorders();
QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y/*, const arma::vec* userP0 = nullptr*/); QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y /*, const arma::vec* userP0 = nullptr*/);
// 根据拟合参数生成曲线 // 根据拟合参数生成曲线
QwtPlotCurve* createFitCurve(const PeakFitResult& result, double xMin, double xMax, const QString& name); QwtPlotCurve* createFitCurve(const PeakFitResult& result, double xMin, double xMax, const QString& name);
@ -143,8 +144,6 @@ private:
// 存储当前显示的拟合曲线,用于清除 // 存储当前显示的拟合曲线,用于清除
QList<QwtPlotCurve*> _fitCurves; QList<QwtPlotCurve*> _fitCurves;
QString _historyFilePath; QString _historyFilePath;
// [NEW] 最近一次拟合结果(用于手动保存) // [NEW] 最近一次拟合结果(用于手动保存)
@ -154,14 +153,13 @@ private:
bool _hasLastFit = false; bool _hasLastFit = false;
QString _workspace; QString _workspace;
//存储当前所有拟合结果(用于多曲线管理) // 存储当前所有拟合结果(用于多曲线管理)
QList<CurrentFitRecord> _currentFitRecords; QList<CurrentFitRecord> _currentFitRecords;
//历史记录列表 // 历史记录列表
QList<PeakFitHistoryItem> _fitHistoryList; QList<PeakFitHistoryItem> _fitHistoryList;
//当前悬停的框选区域 // 当前悬停的框选区域
PlotRectItem* _hoveredRectItem = nullptr; PlotRectItem* _hoveredRectItem = nullptr;
QList<DisplayedCurveRef> _displayedHistoryCurves; QList<DisplayedCurveRef> _displayedHistoryCurves;
}; };
#endif // ENERGYCOUNTPEAKFITVIEW_H #endif // ENERGYCOUNTPEAKFITVIEW_H

View File

@ -106,9 +106,9 @@ void ParticleInjectTimeAnalysisView::setupMenu()
void ParticleInjectTimeAnalysisView::updateData(bool b_init_update) void ParticleInjectTimeAnalysisView::updateData(bool b_init_update)
{ {
_busy_indicator->Start();
auto functionToRun = [this, b_init_update](){ auto functionToRun = [this, b_init_update](){
if(!_data_filename.isEmpty()) { if(!_data_filename.isEmpty()) {
_busy_indicator->Start();
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString(); std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString(); std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString(); std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString();
@ -137,12 +137,14 @@ void ParticleInjectTimeAnalysisView::updateData(bool b_init_update)
if ( y_max < time_count ) if ( y_max < time_count )
y_max = time_count; y_max = time_count;
} }
QMetaObject::invokeMethod(this, [this, x_max, y_max, x, y]() {
_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->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
_curve->setSamples(x, y); _curve->setSamples(x, y);
_plot->replot(); _plot->replot();
LOG_INFO(QStringLiteral(u"%1数据更新完毕.").arg(this->GetViewName())); LOG_INFO(QStringLiteral(u"%1数据更新完毕.").arg(this->GetViewName()));
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
} }
}; };
QThread* load_data_thread = QThread::create(functionToRun); QThread* load_data_thread = QThread::create(functionToRun);

View File

@ -156,17 +156,21 @@ void ParticleTimeDifferenceView::loadDataFromFile()
if ( y_max < count ) if ( y_max < count )
y_max = count; y_max = count;
} }
QMetaObject::invokeMethod(this, [this, samples, x_max, y_max]() {
_histogram->setData(new QwtIntervalSeriesData(samples)); _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->SetAxisInitRange(QwtPlot::yLeft, 0.0f, y_max);
_plot->replot(); _plot->replot();
const QString& info = QStringLiteral(u"粒子时间差分析处理完成."); const QString& info = QStringLiteral(u"粒子时间差分析处理完成.");
LOG_INFO(info); LOG_INFO(info);
}, Qt::QueuedConnection);
} catch (const std::exception& e) { } catch (const std::exception& e) {
const QString& e_what = QString::fromStdString(e.what()); const QString& e_what = QString::fromStdString(e.what());
LOG_WARN(QStringLiteral(u"粒子时间差分析处理异常:%1").arg(e_what)); LOG_WARN(QStringLiteral(u"粒子时间差分析处理异常:%1").arg(e_what));
} }
QMetaObject::invokeMethod(this, [this]() {
_busy_indicator->Stop(); _busy_indicator->Stop();
}, Qt::QueuedConnection);
} }
void ParticleTimeDifferenceView::onActionPlotConfigure() void ParticleTimeDifferenceView::onActionPlotConfigure()