1、添加颜色计算;2、添加测量控制节点;3、调整MainWindow显示

This commit is contained in:
徐海 2026-03-04 21:16:35 +08:00
parent fdfd8611f4
commit f86cbbe3c3
8 changed files with 250 additions and 71 deletions

View File

@ -142,7 +142,7 @@ void MainWindow::initMainWindow()
void MainWindow::initAction()
{
connect(ui->action_new_measurement_analysis, &QAction::triggered, this, [this]() {
auto new_measurement_analysis_handler = [this]() {
NewMeasureAnalysisDlg new_measure_analysis_dlg;
if (QDialog::Accepted == new_measure_analysis_dlg.exec()) {
auto project_model = MeasureAnalysisProjectModelList::GetCurrentProjectModel();
@ -174,7 +174,9 @@ void MainWindow::initAction()
count_task->StartTask();
}
}
});
};
connect(ui->action_new_measurement_analysis, &QAction::triggered, this, new_measurement_analysis_handler);
connect(ui->action_manage_measurement_analysis, &QAction::triggered, this->_action_central_dock_widget, &QAction::triggered);
connect(ui->action_device_config_mrg, &QAction::triggered, this, []() {
QDialog device_cfg_mrg_dlg;
@ -219,21 +221,34 @@ void MainWindow::initAction()
}
if ( !view_exist ) {
ads::CDockWidget* dock_widget = new ads::CDockWidget(view->GetViewName());
auto central_area = _dock_manager->centralWidget()->dockAreaWidget();
CDockAreaWidget* dock_area = _dock_manager->addDockWidget(ads::DockWidgetArea::CenterDockWidgetArea, dock_widget, central_area);
dock_widget->hide();
dock_widget->setWidget(view);
dock_widget->setMinimumSizeHintMode(ads::CDockWidget::MinimumSizeHintFromContentMinimumSize);
if (view->GetAnalyzeViewType() == MeasureAnalysisView::ViewType::DataTable) {
if (view->GetAnalyzeViewType() == MeasureAnalysisViewType::DataTable) {
dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::DockWidgetDeleteOnClose);
_menu_view_data_table_list->addAction(dock_widget->toggleViewAction());
} else {
dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::CustomCloseHandling);
// dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::CustomCloseHandling);
dock_widget->setProperty("TakeWidget", true);
connect(dock_widget, &CDockWidget::closeRequested, [dock_widget](){
dock_widget->takeWidget();
dock_widget->deleteDockWidget();
});
// connect(dock_widget, &CDockWidget::closeRequested, [dock_widget](){
// dock_widget->takeWidget();
// dock_widget->deleteDockWidget();
// });
_menu_view_analysis_view_list->addAction(dock_widget->toggleViewAction());
}
auto central_area = _dock_manager->centralWidget()->dockAreaWidget();
_dock_manager->addDockWidget(ads::DockWidgetArea::CenterDockWidgetArea, dock_widget, central_area);
dock_widget->show();
central_area->update();
central_area->updateGeometry();
dock_area->update();
dock_area->updateGeometry();
dock_widget->update();
dock_widget->updateGeometry();
view->update();
view->updateGeometry();
}
}
});
@ -252,6 +267,8 @@ void MainWindow::initAction()
}
}
});
connect(_tree_measure_analysis, &MeasureAnalysisTree::TreeWidget::newMeasureAnalysisProject, new_measurement_analysis_handler);
}
void MainWindow::applyStyleSheet()

View File

@ -96,6 +96,9 @@ void MeasureAnalysisActions::SetActionsAvailable(const TreeItemType &item_type)
case TreeItemType::ParticleData:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItemType::AnalyzeDataGroup:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItemType::ParticleCountData:
_act_add_analyze_view->setEnabled(true);
break;

View File

@ -10,7 +10,7 @@ MeasureAnalysisDataTableView::MeasureAnalysisDataTableView(QWidget* parent)
, _block_size(100)
, _buffer_size(50)
{
this->setAnalyzeViewType(ViewType::DataTable);
this->setAnalyzeViewType(MeasureAnalysisViewType::DataTable);
QHBoxLayout* layout = new QHBoxLayout(this);
// 创建表格视图
_tableView = new VirtualTableView(this);

View File

@ -2,31 +2,102 @@
#include "qcustomplot.h"
#include "csv.h"
#include <QVector>
#include <GlobalDefine.h>
#include <QHBoxLayout>
QColor getDistinctColorForManyCurves(int curveIndex)
{
// 1. 定义基础色相覆盖不同主色系0-360度
const QList<int> baseHues = {
0, // 红色
30, // 橙色
60, // 黄色
90, // 黄绿色
120, // 绿色
150, // 青绿色
180, // 青色
210, // 天蓝色
240, // 蓝色
270, // 紫色
300, // 洋红色
330 // 玫红色
};
// 2. 定义不同的饱和度/明度组合(避免颜色太暗/太灰)
const QList<QPair<int, int>> sVCombinations = {
{85, 90}, // 高饱和、高明度
{70, 85}, // 中高饱和、中高明度
{85, 75}, // 高饱和、中明度
{60, 80}, // 中饱和、中高明度
{75, 70}, // 中高饱和、中明度
{90, 80} // 极高饱和、中高明度
};
// 3. 计算当前曲线对应的色相和饱和度/明度
int hueIndex = curveIndex % baseHues.size(); // 循环使用基础色相
int svIndex = (curveIndex / baseHues.size()) % sVCombinations.size(); // 循环使用饱和度/明度组合
// 4. 获取HSV参数色相0-360饱和度0-255明度0-255
int hue = baseHues[hueIndex];
int saturation = sVCombinations[svIndex].first * 255 / 100; // 转换为0-255范围
int value = sVCombinations[svIndex].second * 255 / 100; // 转换为0-255范围
// 5. 生成并返回颜色HSV转RGB
QColor color;
color.setHsv(hue, saturation, value);
// 额外优化:避免极浅/极暗的颜色(保证曲线可见)
if (value < 50 * 255 / 100) {
value = 50 * 255 / 100;
color.setHsv(hue, saturation, value);
}
return color;
}
MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent)
: MeasureAnalysisView { parent }
{
this->setAnalyzeViewType(ViewType::CountSpectrum);
this->setAnalyzeViewType(MeasureAnalysisViewType::CountSpectrum);
QHBoxLayout* layout = new QHBoxLayout(this);
_custom_plot = new QCustomPlot(this);
_custom_plot->setGeometry(0, 0, this->width(), this->height());
layout->addWidget(_custom_plot);
setupCustomPlot();
}
void MeasureAnalysisParticleCountPlotView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{
for (auto it = data_files_set.begin(); it != data_files_set.end(); ++it) {
loadDataFromFile(it.value().toString());
loadDataFromFile(it.key(), it.value().toString());
}
_custom_plot->update();
this->update();
}
void MeasureAnalysisParticleCountPlotView::setupCustomPlot()
{
_custom_plot->setNotAntialiasedElements(QCP::aeAll);
_custom_plot->setNoAntialiasingOnDrag(true);
_custom_plot->xAxis->setLabel(QString(QStringLiteral(u"道址")));
_custom_plot->xAxis->setVisible(true);
_custom_plot->yAxis->setLabel(QString(QStringLiteral(u"计数")));
_custom_plot->yAxis->setVisible(true);
_custom_plot->xAxis2->setVisible(true);
_custom_plot->xAxis2->setTickLabels(false);
_custom_plot->xAxis2->setTickLength(0); ;
_custom_plot->yAxis2->setVisible(true);
_custom_plot->yAxis2->setTickLabels(false);
_custom_plot->yAxis2->setTickLength(0); ;
_custom_plot->legend->setVisible(true);
_custom_plot->legend->setSelectableParts(QCPLegend::spItems);
}
void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filename)
void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_name, const QString& filename)
{
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string count_str = QString(QStringLiteral(u"计数")).toStdString();
@ -37,7 +108,7 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filen
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment
> reader(filename.toUtf8().toStdString());
> reader(QStrToSysPath(filename));
reader.read_header(io::ignore_extra_column, address_str, count_str);
int address;
@ -49,9 +120,10 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filen
}
auto graph = _custom_plot->addGraph();
// graph->setPen(QPen(Qt::red));
// graph->setBrush(QBrush(Qt::red));
graph->setName(data_name);
graph->setPen(QPen(getDistinctColorForManyCurves(_custom_plot->graphCount())));
graph->setData(x, y, true);
graph->rescaleAxes();
_custom_plot->replot();
}

View File

@ -17,7 +17,7 @@ public:
private:
void setupCustomPlot();
void loadDataFromFile(const QString& filename);
void loadDataFromFile(const QString &data_name, const QString& filename);
private:
QCustomPlot* _custom_plot { nullptr };

View File

@ -121,25 +121,17 @@ void TreeWidget::SetConnectActions(MeasureAnalysisActions* const actions_analyze
emit newMeasureAnalysisProject();
});
connect(actions_analyze, &MeasureAnalysisActions::rmMeasureAnalysisProject, [this]() {
removeAnalyzeItem();
removeTreeItem(this->currentItem());
});
connect(actions_analyze, &MeasureAnalysisActions::modifyMeasureAnalysisProject, [this]() {
});
connect(actions_analyze, &MeasureAnalysisActions::addAnalyzeView, [this]() {
QString project_name = QString();
MeasureAnalysisViewType view_type = MeasureAnalysisViewType::None;
QTreeWidgetItem* current_item = this->currentItem();
if (!current_item) {
return;
}
TreeItem*
emit newMeasureAnalysisView(MeasureAnalysisView::GetAnalyzeViewTypeText(view_type));
onNewMeasureAnalysisView();
});
connect(actions_analyze, &MeasureAnalysisActions::rmAnalyzeView, [this]() {
removeAnalyzeItem();
removeTreeItem(this->currentItem());
});
connect(actions_analyze, &MeasureAnalysisActions::modifyAnalyzeView, [this]() {
});
@ -150,6 +142,41 @@ void TreeWidget::AddProjectModel(MeasureAnalysisProjectModel* model)
if (model) {
auto new_item = new TreeMeasureAnalysisProjectItem(model->GetProjectName(), model->GetDescriptionInfo());
if (model) {
TreeItem* tree_item_ctrl_group = new_item->GetMeasureCtrlGroupItem();
if (tree_item_ctrl_group) {
const QString& measure_device_params_cfg_filename = model->GetMeasureDeviceParamsCfgFilename();
QMap<QString, QVariant> data_files_set;
data_files_set[QStringLiteral(u"设备参数")] = measure_device_params_cfg_filename;
TreeItem* new_item_dev_params_cfg_data = new TreeItem;
new_item_dev_params_cfg_data->SetName(QStringLiteral(u"测量设备参数"));
new_item_dev_params_cfg_data->SetType(TreeItemType::DeviceConfig);
new_item_dev_params_cfg_data->SetDescription(measure_device_params_cfg_filename);
new_item_dev_params_cfg_data->setData(0, Qt::UserRole, data_files_set);
tree_item_ctrl_group->addChild(new_item_dev_params_cfg_data);
const QString& enery_scale_filename = model->GetEneryScaleFilename();
data_files_set.clear();
data_files_set[QStringLiteral(u"能量刻度")] = enery_scale_filename;
TreeItem* new_item_enery_scale = new TreeItem;
new_item_enery_scale->SetName(QStringLiteral(u"能量刻度"));
new_item_enery_scale->SetType(TreeItemType::EneryScale);
new_item_enery_scale->SetDescription(enery_scale_filename);
new_item_enery_scale->setData(0, Qt::UserRole, data_files_set);
tree_item_ctrl_group->addChild(new_item_enery_scale);
const QString& efficiency_scale_filename = model->GetEfficiencyScaleFilename();
data_files_set.clear();
data_files_set[QStringLiteral(u"效率刻度")] = efficiency_scale_filename;
TreeItem* new_item_efficiency_scale = new TreeItem;
new_item_efficiency_scale->SetName(QStringLiteral(u"效率刻度"));
new_item_efficiency_scale->SetType(TreeItemType::EfficiencyScale);
new_item_efficiency_scale->SetDescription(efficiency_scale_filename);
new_item_efficiency_scale->setData(0, Qt::UserRole, data_files_set);
tree_item_ctrl_group->addChild(new_item_efficiency_scale);
this->expandItem(tree_item_ctrl_group);
}
TreeItem* tree_item_analyze_data_group = new_item->GetAnalyzeDataGroupItem();
if (tree_item_analyze_data_group) {
const QString& all_ch_particle_data_filename = model->GetAllChannelParticleDataFilename();
@ -241,11 +268,11 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name)
uint ch_num = it.key();
const QString& ch_count_filename = it.value();
QMap<QString, QVariant> data_files_set;
data_files_set[QStringLiteral(u"通道%1道址计数数据").arg(ch_num)] = ch_count_filename;
data_files_set[QStringLiteral(u"通道%1").arg(ch_num)] = ch_count_filename;
TreeItem* new_item_every_ch_count_data = new TreeItem;
new_item_every_ch_count_data->SetName(QStringLiteral(u"通道%1道址计数数据").arg(ch_num));
new_item_every_ch_count_data->SetType(TreeItemType::ParticleData);
new_item_every_ch_count_data->SetName(QStringLiteral(u"通道%1道址计数").arg(ch_num));
new_item_every_ch_count_data->SetType(TreeItemType::ParticleCountData);
new_item_every_ch_count_data->SetDescription(ch_count_filename);
new_item_every_ch_count_data->setData(0, Qt::UserRole, data_files_set);
new_item_all_ch_count->addChild(new_item_every_ch_count_data);
@ -257,6 +284,78 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name)
}
}
void TreeWidget::onNewMeasureAnalysisView()
{
TreeItem* current_item = dynamic_cast<TreeItem*>(this->currentItem());
if (!current_item) {
return;
}
TreeMeasureAnalysisProjectItem * project_item = getProjectItem(current_item);
if (!project_item) {
return;
}
TreeItem* new_item_analyze_view = nullptr;
MeasureAnalysisViewType view_type = MeasureAnalysisViewType::None;
TreeItem* tree_item_analyze_view_group = project_item->GetAnalyzeViewGroupItem();
if (tree_item_analyze_view_group) {
MeasureAnalysisTree::TreeItemType item_type = current_item->GetType();
switch (item_type) {
case MeasureAnalysisTree::TreeItemType::ParticleCountData: {
new_item_analyze_view = new TreeItem;
const QString& view_name = QStringLiteral(u"%1谱图表").arg(current_item->GetName());
new_item_analyze_view->SetName(view_name);
new_item_analyze_view->SetDescription(view_name);
new_item_analyze_view->setData(0, Qt::UserRole, current_item->data(0, Qt::UserRole));
const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(MeasureAnalysisViewType::CountSpectrum);
new_item_analyze_view->NewAnalyzeView(view_name, view_name, view_type_text);
} break;
case MeasureAnalysisTree::TreeItemType::AnalyzeDataGroup: {
if ( current_item->childCount() ) {
TreeItem* child_item = dynamic_cast<TreeItem*>(current_item->child(0));
if ( child_item ) {
if ( MeasureAnalysisTree::TreeItemType::ParticleCountData == child_item->GetType() ) {
new_item_analyze_view = new TreeItem;
const QString& view_name = QStringLiteral(u"道址计数谱图表");
new_item_analyze_view->SetName(view_name);
new_item_analyze_view->SetDescription(QStringLiteral(u"32通道的道址计数谱图表"));
auto project_model = MeasureAnalysisProjectModelList::GetProjectModel(project_item->GetName());
QMap<QString, QVariant> data_files_set;
const QMap<uint, QString>& count_data_list = project_model->GetChannelParticleCountDataFilenameList();
for (auto it = count_data_list.begin(); it != count_data_list.end(); ++it) {
uint ch_num = it.key();
const QString& ch_count_filename = it.value();
data_files_set[QStringLiteral(u"通道%1").arg(ch_num)] = ch_count_filename;
}
new_item_analyze_view->setData(0, Qt::UserRole, data_files_set);
const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(MeasureAnalysisViewType::CountSpectrum);
new_item_analyze_view->NewAnalyzeView(view_name, view_name, view_type_text);
}
}
}
} break;
default:
break;
}
}
if ( new_item_analyze_view ) {
new_item_analyze_view->SetType(TreeItemType::AnalyzeView);
MeasureAnalysisView* view = new_item_analyze_view->GetAnalyzeView();
if (view) {
emit currentItemViewWidget(view);
}
tree_item_analyze_view_group->addChild(new_item_analyze_view);
this->expandItem(tree_item_analyze_view_group);
} else {
const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(view_type);
if ( !view_type_text.isEmpty() ) {
}
}
}
void TreeWidget::setCurrentItemHighlight()
{
// 清除之前的高亮
@ -279,60 +378,48 @@ void TreeWidget::setCurrentItemHighlight()
}
}
void TreeWidget::removeAnalyzeItem()
void TreeWidget::removeTreeItem(QTreeWidgetItem* const item)
{
auto current_item = this->currentItem();
if (current_item) {
const QString& text_title = QStringLiteral(u"删除确认");
const QString& text_msg = QStringLiteral(u"是否确定删除\"%1\"?").arg(current_item->text(0));
if (QMessageBox::Yes == QMessageBox::question(nullptr, text_title, text_msg)) {
TreeItem* tree_item = dynamic_cast<TreeItem*>(this->currentItem());
if (tree_item) {
TreeItemType item_type = tree_item->GetType();
if (TreeItemType::MeasureAnalysisProject == item_type) {
} else if (TreeItemType::ParticleData == item_type) {
} else if (TreeItemType::AnalyzeDataGroup == item_type) {
}
MeasureAnalysisView* view = tree_item->GetAnalyzeView();
if (!item) {
return;
}
int count = item->childCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
TreeItem* child_item = dynamic_cast<TreeItem*>(item->child(0));
if (child_item) {
MeasureAnalysisView* view = child_item->GetAnalyzeView();
if (view) {
emit removeItemViewFromStack(view);
}
}
this->removeTreeItem(current_item);
removeTreeItem(child_item);
}
}
}
void TreeWidget::removeTreeItem(QTreeWidgetItem* const item)
{
int count = item->childCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
QTreeWidgetItem* childItem = item->child(0);
removeTreeItem(childItem);
TreeItem* tree_item = dynamic_cast<TreeItem*>(item);
if (tree_item) {
MeasureAnalysisView* view = tree_item->GetAnalyzeView();
if (view) {
emit removeItemViewFromStack(view);
}
}
delete item;
}
}
MeasureAnalysisTree::TreeMeasureAnalysisProjectItem *MeasureAnalysisTree::TreeWidget::getProjectItem(TreeItem *item)
{
if (item) {
TreeItemType item_type = item->GetType();
if (TreeItemType::MeasureAnalysisProject == item_type) {
return dynamic_cast<TreeMeasureAnalysisProjectItem*>(item);
}
} else {
item = dynamic_cast<TreeItem*>(item->parent());
if (item) {
return getProjectItem(item);
} else {
item = dynamic_cast<TreeItem*>(item->parent());
if (item) {
return getProjectItem(item);
}
}
}
return nullptr;
}
// namespace MeasureAnalysisTree
} // namespace MeasureAnalysisTree

View File

@ -31,17 +31,16 @@ private slots:
// void onFinishedSeparateEveryChannelParticleData(const QString& project_name);
void onFinishedParticleSortData(const QString& project_name);
void onFinishedParticleCountData(const QString& project_name);
void onNewMeasureAnalysisView();
signals:
void currentItemViewWidget(MeasureAnalysisView* view);
void removeItemViewFromStack(MeasureAnalysisView* view);
void newMeasureAnalysisProject();
void newMeasureAnalysisView(const QString& project_name, const QString& view_type);
private:
void setCurrentItemHighlight();
void removeAnalyzeItem();
void removeTreeItem(QTreeWidgetItem* const item);
};

View File

@ -1,6 +1,7 @@
#include "MeasureAnalysisView.h"
#include <QMap>
#include "MeasureAnalysisDataTableView.h"
#include "MeasureAnalysisParticleCountPlotView.h"
QMap<QString, MeasureAnalysisViewType> MeasureAnalysisView::_s_analyze_view_type_list {
{ QStringLiteral(u"数据表视图"),
@ -37,7 +38,7 @@ MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(const QString& view_typ
new_view = new MeasureAnalysisDataTableView;
} break;
case MeasureAnalysisViewType::CountSpectrum: {
new_view = new MeasureAnalysisDataTableView;
new_view = new MeasureAnalysisParticleCountPlotView;
} break;
case MeasureAnalysisViewType::CoincidenceEnergySpectrum3D: {
new_view = new MeasureAnalysisDataTableView;