Compare commits

..

2 Commits

Author SHA1 Message Date
anxinglong
7219460e45 Merge branch 'dev' of http://git.hivekion.com:3000/xuhai_cpp/EnergySpectrumAnalyer into dev 2026-03-26 17:36:43 +08:00
anxinglong
5d808b6264 三维视图显示 2026-03-26 17:35:58 +08:00
14 changed files with 2576 additions and 4 deletions

View File

@ -56,7 +56,6 @@ void MeasureAnalysisTreeView::onCustomContextMenuRequested(const QPoint& pos)
QVariant user_data = _model->GetNodeUserData(item);
}
void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
{
if (!index.isValid())
@ -218,9 +217,9 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
case AnalysisType::CoincidenceParticleEnergySpectrum3DView: {
MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name);
if (project_model) {
auto file_name = project_model->GetAllChannelParticleDataFilename();
if ( !file_name.isEmpty() ) {
data_files_set[QStringLiteral(u"符合粒子能量3D视图")] = file_name;
auto file_name_list = project_model->GetTimeWinConformEnergyDataFilenameList(project_model->GetConformTimeWin());
for (auto it = file_name_list.constBegin(); it!=file_name_list.constEnd(); ++it) {
data_files_set[QString::number(it.key())] = it.value();
}
}
} break;

View File

@ -0,0 +1,75 @@
#ifndef COINCIDENCESPECTRUMPROCESS_H
#define COINCIDENCESPECTRUMPROCESS_H
#include <armadillo>
// 定义板卡和通道的最大数量
static constexpr int MAX_BOARD = 8;
static constexpr int MAX_CHANNEL = 4;
// 用于存储三维数据
typedef struct SurfacePoint {
float primaryEnergy; // 初级粒子能量
float secondaryEnergySum; // 次级粒子能量和
int count; // 符合事件计数
}SURFACEPOINT;
namespace CoincidenceSpectrum {
// 二次符合事件筛选
arma::mat EventFilter2Order(const arma::mat& raw_spec_data, double conformity_event_time_win = 50.0f);
// 计算二维直方图
void Hist3(const arma::mat& data, int nx, int ny, arma::mat& counts, arma::vec& x_edges, arma::vec& y_edges);
// 二次符合事件处理
namespace F2t9Order {
// 能谱数据结构
struct SpectrumData {
int board_id; // 板卡号
int channel_id; // 通道号
double energy; // 能量
unsigned long long timestamp; // 时间戳(纳秒)
};
// 符合事件结果结构
struct CoincidenceEvent {
int coincidence_order; // 符合次数2-9
std::vector<SpectrumData> events; // 符合的事件集合
unsigned int time_window; // 使用的时间窗口(秒)
};
// 读取CSV数据文件
std::vector<SpectrumData> ReadCsv(const std::string& filename);
// 按时间戳排序数据
void SortDataByTimestamp(std::vector<SpectrumData>& data);
// 2-9次能谱符合处理
std::vector<CoincidenceEvent> ProcessCoincidence(
const std::vector<SpectrumData>& data,
unsigned int time_window, // 时间窗口(纳秒)
int min_order = 2, // 最小符合次数
int max_order = 9 // 最大符合次数
);
// 统计符合事件结果
arma::mat AnalyzeCoincidenceResults(
const std::vector<CoincidenceEvent>& results,
int max_order = 9
);
// 保存结果到文件
void SaveResults(
const std::vector<CoincidenceEvent>& results,
const arma::mat& stats,
const std::string& base_filename = "coincidence_results"
);
};
}
#endif // COINCIDENCESPECTRUMPROCESS_H

View File

@ -0,0 +1,301 @@
#include "ConformityAnalysis.h"
#include "ui_ConformityAnalysis.h"
#include <QDebug>
ConformityAnalysis::ConformityAnalysis(QWidget *parent) :
MeasureAnalysisView(parent),
ui(new Ui::ConformityAnalysis)
{
ui->setupUi(this);
memset(m_boardChannel, 0, sizeof(m_boardChannel)); // 新增
//// // 获取当前可执行文件的路径
//// QString executablePath = QCoreApplication::applicationDirPath() + "/test.csv";
// connect(ui->widget,SIGNAL(Signal_ClickedBoard(int,int)),this,SLOT(slot_ClickedBoard(int,int)));
// connect(ui->widget,SIGNAL(Signal_InitialState()),this,SLOT(slot_InitialState()));
//// qDebug()<<"可执行文件:"<< executablePath;
// setCsvFile(m_fileName);
// readCsv();
// handleBoard();
// m_FirstParticle = statisticsFirstParticleQuantity();
// setAllBoardData();
// calculateFirstSecondRange();
// setThreeUiData();
// generateSurfaceData(m_CoincidenceEventVector);
}
ConformityAnalysis::~ConformityAnalysis()
{
delete ui;
}
void ConformityAnalysis::InitViewWorkspace(const QString &project_name)
{
}
void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{
QStringList ch_count_data_name = data_files_set.keys();
int conformCount = ui->comboBox->currentIndex() + 2;
for (const QString& ch_count_data_name : ch_count_data_name) {
qDebug()<<data_files_set[ch_count_data_name];
if(conformCount == ch_count_data_name.toInt())
{
setCsvFile(data_files_set[ch_count_data_name].toString());
readCsv();
handleBoard();
m_FirstParticle = statisticsFirstParticleQuantity();
setAllBoardData();
calculateFirstSecondRange();
setThreeUiData();
generateSurfaceData(m_CoincidenceEventVector);
}
}
// QString path = data_files_set.first().toString();
// qDebug()<<path;
// setCsvFile(path);
}
void ConformityAnalysis::setCsvFile(QString fileName)
{
m_fileName = fileName;
}
void ConformityAnalysis::readCsv()
{
qDebug()<<m_fileName;
// 创建 CSVReader 对象指定列数5列
io::CSVReader<5> reader(m_fileName.toStdString());
qDebug()<<"板卡号:";
// 符合事件变量
int id = 0;
std::vector<F2t9Order::SpectrumData> SpectrumDataList;
// 逐行读取数据
while (true)
{
int comply = 0;
F2t9Order::SpectrumData SpectrumData;
bool flag = reader.read_row(/*EventData.coincidence_order*/comply,SpectrumData.board_id, SpectrumData.channel_id, SpectrumData.energy,SpectrumData.timestamp);
qDebug()<<"符合事件:"<<comply<<"板卡号:"<<SpectrumData.board_id<<"通道号:"<<SpectrumData.board_id<<"能量:"<<SpectrumData.energy<<"时间戳:"<<SpectrumData.timestamp;
if(!flag)
{
break;
}
SpectrumDataList.push_back(SpectrumData);
if(comply != id)
{
F2t9Order::CoincidenceEvent EventData;
EventData.coincidence_order = comply;
EventData.events = SpectrumDataList;
m_CoincidenceEventVector.push_back(EventData);
qDebug()<<"符合事件里面的vector"<<EventData.events.size();
id = EventData.coincidence_order;
SpectrumDataList.clear();
}
}
qDebug()<<"符合事件数:"<<m_CoincidenceEventVector.size();
}
void ConformityAnalysis::slot_InitialState()
{
setAllBoardData();
calculateFirstSecondRange();
setThreeUiData();
generateSurfaceData(m_CoincidenceEventVector);
}
void ConformityAnalysis::slot_ClickedBoard(int board,int channel)
{
//获取当前板卡的初级粒子数据
std::vector<F2t9Order::CoincidenceEvent> data = handleBasicSubordinate(m_CoincidenceEventVector,board,channel);
if(data.size() <= 0) return;
generateSurfaceData(data);
m_subordinate = handleSubordinate(data, board, channel);
for (int i = 0; i < m_subordinate.keys().size();i++)
{
QString objectName =m_subordinate.keys().at(i);
QStringList parts = objectName.split('_');
int bd = parts[1].toInt();
int ch = parts[2].toInt();
ui->widget->setWidgetData(bd,ch,m_boardChannel[bd - 1][ch - 1],m_subordinate[objectName]);
}
ui->widget->setWidgetData(board,channel,m_boardChannel[board - 1][channel - 1],data.size());
}
void ConformityAnalysis::handleBoard()
{
for (int i = 0; i < m_CoincidenceEventVector.size(); i++)
{
for(auto spetruData:m_CoincidenceEventVector.at(i).events)
{
m_boardChannel[spetruData.channel_id][spetruData.board_id]++;
}
}
}
QMap<QString, int> ConformityAnalysis::statisticsFirstParticleQuantity()
{
QMap<QString, int> firstParticleCount;
// 初始化所有板卡通道的计数为0
for (int board = 1; board <= 8; ++board)
{
for (int channel = 1; channel <= 4; ++channel)
{
QString key = QString("widget_%1_%2").arg(board).arg(channel);
firstParticleCount[key] = 0;
}
}
// 遍历所有符合事件
for (const auto& event : m_CoincidenceEventVector)
{
if (event.events.empty()) continue;
// 第一个事件是初级粒子
const auto& firstParticle = event.events[0];
int boardId = firstParticle.board_id + 1; // 转换为1-based
int channelId = firstParticle.channel_id + 1; // 转换为1-based
if (boardId >= 1 && boardId <= 8 && channelId >= 1 && channelId <= 4) {
QString key = QString("widget_%1_%2").arg(boardId).arg(channelId);
firstParticleCount[key]++;
}
}
return firstParticleCount;
}
std::vector<F2t9Order::CoincidenceEvent> ConformityAnalysis::handleBasicSubordinate(std::vector<F2t9Order::CoincidenceEvent> &eventData, int Board, int Channel)
{
std::vector<F2t9Order::CoincidenceEvent> EventVector;//所有的初级粒子符合事件
for (int i = 0; i < eventData.size(); i++)
{
F2t9Order::CoincidenceEvent EventData = eventData.at(i);
F2t9Order::SpectrumData data = EventData.events.at(0);
if (data.board_id == Board - 1&& data.channel_id == Channel - 1)
{
EventVector.push_back(EventData);
m_beginVector.push_back(data);
}
}
return EventVector;
}
QMap<QString, int> ConformityAnalysis::handleSubordinate(std::vector<F2t9Order::CoincidenceEvent> &eventData,int Board, int Channel)
{
m_secondVector.clear();
QMap<QString, int> data;
for (int board = 1; board <= 8; ++board)
{
for (int channel = 1; channel <= 4; ++channel)
{
QString key = QString("widget_%1_%2").arg(board).arg(channel);
data[key] = 0;
for (int j = 0; j < eventData.size(); j++)
{
std::vector<F2t9Order::SpectrumData> dataVector = eventData.at(j).events;
for (int k = 0; k < dataVector.size(); k++)
{
F2t9Order::SpectrumData dataSpectrum = dataVector.at(k);
if (dataSpectrum.board_id == Board - 1 && dataSpectrum.channel_id == Channel - 1)
continue;
if (dataSpectrum.board_id == board - 1 && dataSpectrum.channel_id == channel - 1)
{
data[key]++;
m_secondVector.push_back(dataSpectrum);
}
}
}
}
}
return data;
}
int ConformityAnalysis::getMaxValue()
{
auto begin = &m_boardChannel[0][0];
auto end = begin + MAX_BOARD * MAX_CHANNEL;
return *std::max_element(begin, end);
}
void ConformityAnalysis::calculateFirstSecondRange()
{
//符合事件总计数
m_iComply = 0;
// 找出所有数值中的最小值和最大值
double minFirstVal = 11111111.1111;
double maxFirstVal = 0.0;
double minSecondVal = 11111111.1111;
double maxSecondVal = 0.0;
for (int i = 0; i < m_CoincidenceEventVector.size(); i++)
{
F2t9Order::CoincidenceEvent data = m_CoincidenceEventVector.at(i);
m_iComply += data.events.size();
for (int j = 0; j < data.events.size(); j++)
{
F2t9Order::SpectrumData spectrum = data.events.at(j);
if (j == 0)
{
if (spectrum.energy < minFirstVal) minFirstVal = spectrum.energy;
if (spectrum.energy > maxFirstVal) maxFirstVal = spectrum.energy;
continue;
}
if (spectrum.energy < minSecondVal) minSecondVal = spectrum.energy;
if (spectrum.energy > maxSecondVal) maxSecondVal = spectrum.energy;
}
}
m_dFirstStart = minFirstVal;
m_dFirstEnd = maxFirstVal;
m_dSecondStart = minSecondVal;
m_dSecondEnd = maxSecondVal;
}
void ConformityAnalysis::setAllBoardData()
{
for (int board = 1; board <= 8; ++board)
{
for (int channel = 1; channel <= 4; ++channel)
{
QString key = QString("widget_%1_%2").arg(board).arg(channel);
qDebug()<<key;
if ( m_FirstParticle.contains(key) ) {
ui->widget->setInitWidgetData(board,channel,m_boardChannel[board - 1][channel-1],m_FirstParticle[key]);
}
}
}
}
void ConformityAnalysis::setThreeUiData()
{
qDebug()<< m_dSecondStart << m_dSecondEnd;
ui->widget_3D->setBasicParticle(m_dFirstStart,m_dFirstEnd);
ui->widget_3D->setSecondParticle(m_dSecondStart,m_dSecondEnd);
ui->widget_3D->setComplyWithEvent(m_iComply);
}
void ConformityAnalysis::generateSurfaceData(const std::vector<F2t9Order::CoincidenceEvent>& events)
{
m_surfaceData.clear();
for (const auto& event : events)
{
if (event.events.empty()) continue;
float primaryEnergy = event.events[0].energy;
float secondaryEnergySum = 0.0f;
for (size_t i = 1; i < event.events.size(); i++) {
secondaryEnergySum += event.events[i].energy;
}
SurfacePoint point;
point.primaryEnergy = primaryEnergy;
point.secondaryEnergySum = secondaryEnergySum;
point.count = 1;
m_surfaceData.append(point);
}
ui->widget_3D->setSurfaceData(m_surfaceData);
}

View File

@ -0,0 +1,86 @@
#ifndef CONFORMITYANALYSIS_H
#define CONFORMITYANALYSIS_H
#include <QWidget>
#include <iostream>
#include "ParticleDataStatistics.h"
#include "ThreeDDisplay.h"
#include "csv.h"
#include "CoincidenceSpectrumProcess.h"
#include "MeasureAnalysisView.h"
using namespace CoincidenceSpectrum;
namespace Ui {
class ConformityAnalysis;
}
class ConformityAnalysis : public MeasureAnalysisView
{
Q_OBJECT
private:
QMap<QString, int> m_FirstParticle;
QMap<QString, int> m_subordinate;
std::vector<F2t9Order::SpectrumData> m_beginVector;
std::vector<F2t9Order::SpectrumData> m_secondVector;
QVector<SurfacePoint> m_surfaceData;
public:
explicit ConformityAnalysis(QWidget *parent = nullptr);
~ConformityAnalysis();
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
//设置csv文件路径及文件名称
void setCsvFile(QString fileName);
//读取csv文件
void readCsv();
private slots:
void slot_InitialState();
void slot_ClickedBoard(int board,int channel);
private:
//处理板卡信息
void handleBoard();
//统计每个板卡的初级粒子计数
QMap<QString, int> statisticsFirstParticleQuantity();
//处理当前板卡初级粒子信息
std::vector<F2t9Order::CoincidenceEvent> handleBasicSubordinate(std::vector<F2t9Order::CoincidenceEvent> &eventData,int Board, int Channel);
//处理次级粒子信息
QMap<QString,int> handleSubordinate(std::vector<F2t9Order::CoincidenceEvent> &eventData, int Board, int Channel);
// 获取最大值
int getMaxValue();
//计算全部的初级粒子范围 和 次级粒子范围
void calculateFirstSecondRange();
//设置板卡数据信息
void setAllBoardData();
//设置符合事件相关信息
void setThreeUiData();
//全部谱图数据处理
void generateSurfaceData(const std::vector<F2t9Order::CoincidenceEvent>& events);
private:
Ui::ConformityAnalysis *ui;
QString m_fileName;
std::vector<F2t9Order::CoincidenceEvent> m_CoincidenceEventVector;//所有的能谱符合处理
int m_boardChannel[MAX_BOARD][MAX_CHANNEL];
double m_dFirstStart = 0.0;//初级粒子起始能量
double m_dFirstEnd = 0.0;//初级粒子终止能量
double m_dSecondStart = 0.0;//初级粒子起始能量
double m_dSecondEnd = 0.0;//初级粒子终止能量
int m_iComply = 0;//符合事件总计数
};
#endif // CONFORMITYANALYSIS_H

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConformityAnalysis</class>
<widget class="QWidget" name="ConformityAnalysis">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="windowTitle">
<string>ConformityAnalysis</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,20">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>通过在下图中框选区域,自动识别出符合时间进入下方列表,选择符合时间右侧界面内进行统计</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>符合时间窗:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit">
<property name="text">
<string>50</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>ns</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>修改</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>选择符合事件:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<property name="minimumSize">
<size>
<width>100</width>
<height>22</height>
</size>
</property>
<item>
<property name="text">
<string>二次符合</string>
</property>
</item>
<item>
<property name="text">
<string>三次符合</string>
</property>
</item>
<item>
<property name="text">
<string>四次符合</string>
</property>
</item>
<item>
<property name="text">
<string>五次符合</string>
</property>
</item>
<item>
<property name="text">
<string>六次符合</string>
</property>
</item>
<item>
<property name="text">
<string>七次符合</string>
</property>
</item>
<item>
<property name="text">
<string>八次符合</string>
</property>
</item>
<item>
<property name="text">
<string>九次符合</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="2,4">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="ThreeDDisplay" name="widget_3D" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="ParticleDataStatistics" name="widget" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>ThreeDDisplay</class>
<extends>QWidget</extends>
<header>ThreeDDisplay.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ParticleDataStatistics</class>
<extends>QWidget</extends>
<header>ParticleDataStatistics.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,209 @@
#include "DetectorStatusSummary.h"
#include "ui_DetectorStatusSummary.h"
#include <QPainter>
#include <QMouseEvent>
DetectorStatusSummary::DetectorStatusSummary(QWidget *parent) :
QWidget(parent),
ui(new Ui::DetectorStatusSummary)
{
ui->setupUi(this);
}
DetectorStatusSummary::~DetectorStatusSummary()
{
delete ui;
}
void DetectorStatusSummary::setName(QString name)
{
ui->label_name->setText(name);
}
void DetectorStatusSummary::setCountName(QString name)
{
ui->label->setText(name);
}
void DetectorStatusSummary::setNum(int num)
{
m_nNum = num;
ui->label_num->setText(QString::number(num));
}
QString DetectorStatusSummary::getCountNum()
{
return ui->label_num->text();
}
void DetectorStatusSummary::setBeginSecond(QString str)
{
ui->label_begin_second->setText(str);
}
void DetectorStatusSummary::setBeginSecondNum(int num)
{
ui->label_begin_second_num->setText(QString::number(num));
}
QString DetectorStatusSummary::getBeginSecondNum()
{
return ui->label_begin_second_num->text();
}
void DetectorStatusSummary::setBeginSecondWidget(bool isHide)
{
if (isHide)
{
ui->label_begin_second->hide();
ui->label_begin_second_num->hide();
}
else
{
ui->label_begin_second->show();
ui->label_begin_second_num->show();
}
}
void DetectorStatusSummary::setColorMaxValue(int maxValue)
{
m_nMaxValue = maxValue;
}
void DetectorStatusSummary::setInitWidgetColor()
{
QPainter p(this);
QString strqs = "min-height:35px;max-height:35px;";
p.fillRect(rect(), QColor("#0E508A")); // 仅自己区域
ui->label_name->setStyleSheet("background-color: #1E79C2;color:#FFFFFF;"+strqs);
ui->label->setStyleSheet("color:#4CA9F9;");
ui->label_num->setStyleSheet("background-color: #125997;color:#FFFFFF;font-size: 30px; font-family: Microsoft YaHei; ");
ui->widget_dw->setStyleSheet("background-color: #1B66A7;color:#FFFFFF;" + strqs);
m_useCustomColor = false;
update();
}
void DetectorStatusSummary::setHideBorder()
{
ui->widget->setStyleSheet("");
flag = false;
}
void DetectorStatusSummary::setBackgroundColor(const QColor &color)
{
m_backgroundColor = color;
//QPainter painter(this);
//painter.setRenderHint(QPainter::Antialiasing);
////// 创建渐变背景
////QLinearGradient gradient(0, 0, width(), 0);
////gradient.setColorAt(0.0, m_backgroundColor.lighter(110));
////gradient.setColorAt(0.5, m_backgroundColor);
////gradient.setColorAt(1.0, m_backgroundColor.darker(110));
//// 绘制背景
//painter.fillRect(rect(), m_backgroundColor);
//QString strColor = QString("rgb(%1,%2,%3,1)").arg(m_backgroundColor.red()).arg(m_backgroundColor.green()).arg(m_backgroundColor.blue());
//ui.widget_dw->setStyleSheet(QString("background-color: %1;color:#FFFFFF;").arg(strColor));
//// 绘制边框
//painter.setPen(QPen(QColor(23, 99, 162), 1));
//painter.drawRect(rect().adjusted(0, 0, -1, -1));
update(); // 触发重绘
}
void DetectorStatusSummary::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
// QPainter painter(this);
// painter.setRenderHint(QPainter::Antialiasing);
// //// 创建渐变背景
// //QLinearGradient gradient(0, 0, width(), 0);
// //gradient.setColorAt(0.0, m_backgroundColor.lighter(110));
// //gradient.setColorAt(0.5, m_backgroundColor);
// //gradient.setColorAt(1.0, m_backgroundColor.darker(110));
// // 绘制背景
// painter.fillRect(rect(), m_backgroundColor);
// QString strColor = QString("rgb(%1,%2,%3,1)").arg(m_backgroundColor.red()).arg(m_backgroundColor.green()).arg(m_backgroundColor.blue());
// ui->widget_dw->setStyleSheet(QString("background-color: %1;color:#FFFFFF;").arg(strColor));
// ui->label->setStyleSheet(QString("background-color: %1;color:#FFFFFF;").arg(strColor));
// ui->label_num->setStyleSheet(QString("background-color: %1;color:#FFFFFF;font-size: 30px; font-family: Microsoft YaHei; ").arg(strColor));
// // 绘制边框
// painter.setPen(QPen(QColor(23, 99, 162), 1));
// painter.drawRect(rect().adjusted(0, 0, -1, -1));
}
QColor DetectorStatusSummary::calculateGradientColor(double ratio)
{
// 四段式渐变:蓝->蓝绿->黄->橙->红
QColor color;
if (ratio < 0.25) {
// 蓝到蓝绿
double subRatio = ratio / 0.25;
color = QColor(
14 + (51 - 14) * subRatio, // R: 14->51
80 + (102 - 80) * subRatio, // G: 80->102
138 + (153 - 138) * subRatio // B: 138->153
);
}
else if (ratio < 0.5) {
// 蓝绿到黄
double subRatio = (ratio - 0.25) / 0.25;
color = QColor(
51 + (244 - 51) * subRatio, // R: 51->244
102 + (196 - 102) * subRatio, // G: 102->196
153 + (34 - 153) * subRatio // B: 153->34
);
}
else if (ratio < 0.75) {
// 黄到橙
double subRatio = (ratio - 0.5) / 0.25;
color = QColor(
244 + (239 - 244) * subRatio, // R: 244->239
196 + (155 - 196) * subRatio, // G: 196->155
34 + (57 - 34) * subRatio // B: 34->57
);
}
else {
// 橙到红
double subRatio = (ratio - 0.75) / 0.25;
color = QColor(
239 + (255 - 239) * subRatio, // R: 239->255
155 + (51 - 155) * subRatio, // G: 155->51
57 + (76 - 57) * subRatio // B: 57->76
);
}
return color;
}
void DetectorStatusSummary::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && flag == false)
{
if ((ui->label_num->text().toInt() == 0 )&& (ui->label_begin_second_num->text().toInt() == 0))
return;
ui->widget->setStyleSheet("QWidget#widget{border: 2px solid #ffffff;}");
// 可以发出信号
emit oneclicked(objectName());
flag = true;
}
else
{
if ((ui->label_num->text().toInt() == 0 )&& (ui->label_begin_second_num->text().toInt() == 0))
return;
ui->widget->setStyleSheet("");
// 可以发出信号
emit twoClicked(objectName());
flag = false;
}
// 调用基类实现
QWidget::mousePressEvent(event);
}

View File

@ -0,0 +1,74 @@
#ifndef DETECTORSTATUSSUMMARY_H
#define DETECTORSTATUSSUMMARY_H
#include <QWidget>
namespace Ui {
class DetectorStatusSummary;
}
class DetectorStatusSummary : public QWidget
{
Q_OBJECT
public:
explicit DetectorStatusSummary(QWidget *parent = nullptr);
~DetectorStatusSummary();
//设置名称
void setName(QString name);
//设置总计数名称
void setCountName(QString name);
//设置数量
void setNum(int num);
//获取总计数
QString getCountNum();
//设置初 次级粒子计数
void setBeginSecond(QString str);
//设置初 次级粒子计数 数量
void setBeginSecondNum(int num);
//获取
QString getBeginSecondNum();
//设置初级粒子计数隐藏
void setBeginSecondWidget(bool isHide);
//设置最大值
void setColorMaxValue(int maxValue);
//设置初始底色
void setInitWidgetColor();
//设置隐藏边框
void setHideBorder();
/*--------------------设置颜色---------------------------*/
// 直接设置颜色由ConformanceAnalysis调用
void setBackgroundColor(const QColor& color);
protected:
// 添加paintEvent声明
void paintEvent(QPaintEvent *event) override;
private:
// 计算渐变颜色
QColor calculateGradientColor(double ratio);
// 添加私有成员
QColor m_backgroundColor;
bool m_useCustomColor = false;
/*-------------------------------------------------------*/
protected:
/*void paintEvent(QPaintEvent *) override;*/
void mousePressEvent(QMouseEvent *event) override;
signals:
void oneclicked(QString value);
void twoClicked(QString value);
private:
Ui::DetectorStatusSummary *ui;
// 计数器数值
int m_nNum;
// 点击标志
bool flag = false;
// 自适应色阶相关
int m_nMaxValue = 200; // 当前最大值
};
#endif // DETECTORSTATUSSUMMARY_H

View File

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DetectorStatusSummary</class>
<widget class="QWidget" name="DetectorStatusSummary">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>134</width>
<height>156</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_name">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>33</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>总计数:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_num">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>45</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget_dw" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_begin_second">
<property name="text">
<string>次级粒子计数:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_begin_second_num">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,137 @@
#include "ParticleDataStatistics.h"
#include "ui_ParticleDataStatistics.h"
#include <QDebug>
ParticleDataStatistics::ParticleDataStatistics(QWidget *parent) :
QWidget(parent),
ui(new Ui::ParticleDataStatistics)
{
ui->setupUi(this);
InitUi();
}
ParticleDataStatistics::~ParticleDataStatistics()
{
delete ui;
}
void ParticleDataStatistics::InitUi()
{
m_widgetMap[0][0] = ui->widget_1_1;
m_widgetMap[0][1] = ui->widget_1_2;
m_widgetMap[0][2] = ui->widget_1_3;
m_widgetMap[0][3] = ui->widget_1_4;
m_widgetMap[1][0] = ui->widget_2_1;
m_widgetMap[1][1] = ui->widget_2_2;
m_widgetMap[1][2] = ui->widget_2_3;
m_widgetMap[1][3] = ui->widget_2_4;
m_widgetMap[2][0] = ui->widget_3_1;
m_widgetMap[2][1] = ui->widget_3_2;
m_widgetMap[2][2] = ui->widget_3_3;
m_widgetMap[2][3] = ui->widget_3_4;
m_widgetMap[3][0] = ui->widget_4_1;
m_widgetMap[3][1] = ui->widget_4_2;
m_widgetMap[3][2] = ui->widget_4_3;
m_widgetMap[3][3] = ui->widget_4_4;
m_widgetMap[4][0] = ui->widget_5_1;
m_widgetMap[4][1] = ui->widget_5_2;
m_widgetMap[4][2] = ui->widget_5_3;
m_widgetMap[4][3] = ui->widget_5_4;
m_widgetMap[5][0] = ui->widget_6_1;
m_widgetMap[5][1] = ui->widget_6_2;
m_widgetMap[5][2] = ui->widget_6_3;
m_widgetMap[5][3] = ui->widget_6_4;
m_widgetMap[6][0] = ui->widget_7_1;
m_widgetMap[6][1] = ui->widget_7_2;
m_widgetMap[6][2] = ui->widget_7_3;
m_widgetMap[6][3] = ui->widget_7_4;
m_widgetMap[7][0] = ui->widget_8_1;
m_widgetMap[7][1] = ui->widget_8_2;
m_widgetMap[7][2] = ui->widget_8_3;
m_widgetMap[7][3] = ui->widget_8_4;
for(int bd = 0; bd < MAX_BOARD;bd++ )
{
for (int ch = 0;ch < MAX_CHANNEL;ch++)
{
QString name = QString("板卡%1(通道%2)").arg(bd + 1).arg(ch + 1);
m_widgetMap[bd][ch]->setName(name);
// 连接探测器点击信号到处理槽函数
connect(m_widgetMap[bd][ch],SIGNAL(oneclicked(QString)),this,SLOT(_slotClickedBoard(QString)));
connect(m_widgetMap[bd][ch], SIGNAL(twoClicked(QString)), this, SLOT(_slotClickedTwoBoard(QString)));
}
}
}
void ParticleDataStatistics::_slotClickedBoard(QString board)
{
QStringList parts = board.split('_');
m_bd = parts[1].toInt();//获取初级粒子板卡号
m_ch = parts[2].toInt();//获取初级粒子通道号
emit Signal_ClickedBoard(m_bd,m_ch);
QList<DetectorStatusSummary*> pdetorList = this->findChildren<DetectorStatusSummary*>();
for (int i = 0; i < pdetorList.size(); i++)
{
if (pdetorList.at(i)->objectName() != board)
pdetorList.at(i)->setHideBorder();
// QColor color = getColorForValue(0);
// pdetorList.at(i)->setBackgroundColor(color);
}
}
void ParticleDataStatistics::_slotClickedTwoBoard(QString board)
{
emit Signal_InitialState();//发送信号更新数据至初始值
}
void ParticleDataStatistics::setWidgetData(int board, int channel, int countNum, int secondNum)
{
// 参数合法性检查(防止越界)
if (board < 1 || board > MAX_BOARD || channel < 1 || channel > MAX_CHANNEL) {
qWarning() << "setWidgetData: invalid board or channel:" << board << channel;
return;
}
DetectorStatusSummary* widget = m_widgetMap[board - 1][channel - 1];
if (widget)
{
//当板卡号和通道号都为-1时 设置为为点击状态
if(board == -1 && channel == -1)
{
widget->setCountName("总计数");
widget->setNum(countNum);
widget->setBeginSecond("初级粒子计数");
widget->setBeginSecondNum(secondNum);
return ;
}
//当板卡号和点击的板卡号相同时 设置为初级粒子
if(board == m_bd && channel == m_ch)
{
widget->setCountName("初级粒子计数");
widget->setNum(secondNum);
widget->setBeginSecond("总计数");
widget->setBeginSecondNum(countNum);
}
else//否则为次级粒子
{
widget->setCountName("次级粒子计数");
widget->setNum(secondNum);
widget->setBeginSecond("总计数");
widget->setBeginSecondNum(countNum);
}
}
}
void ParticleDataStatistics::setInitWidgetData(int board, int channel, int countNum, int secondNum)
{
DetectorStatusSummary* widget = m_widgetMap[board - 1][channel - 1];
if(widget==nullptr)
{
return;
}
widget->setCountName("总计数");
widget->setNum(countNum);
widget->setBeginSecond("初级粒子计数");
widget->setBeginSecondNum(secondNum);
}

View File

@ -0,0 +1,55 @@
#ifndef PARTICLEDATASTATISTICS_H
#define PARTICLEDATASTATISTICS_H
#include <QWidget>
#include "DetectorStatusSummary.h"
#include "CoincidenceSpectrumProcess.h"
#include <QMap>
using namespace CoincidenceSpectrum;
namespace Ui {
class ParticleDataStatistics;
}
class ParticleDataStatistics : public QWidget
{
Q_OBJECT
public:
explicit ParticleDataStatistics(QWidget *parent = nullptr);
~ParticleDataStatistics();
void setWidgetData(int board, int channel, int countNum, int secondNum);
void setInitWidgetData(int board, int channel, int countNum, int secondNum);
//处理板卡信息
void handleBoard(std::vector<F2t9Order::SpectrumData> eventData);
//设置数据
void setCoincidenceEvent(const F2t9Order::CoincidenceEvent &CoincidenceEvent);
private:
// 初始化映射表
void InitUi();
//统计每个板卡的初级粒子计数
QMap<QString, int> statisticsFirstParticleQuantity();
//处理初级粒子信息
std::vector<F2t9Order::SpectrumData> handleBasicSubordinate(std::vector<F2t9Order::SpectrumData> dataList,int Board, int Channel);
private slots:
//点击板卡探测器时触发的函数 区分初级粒子和次级粒子计数
void _slotClickedBoard(QString board);
void _slotClickedTwoBoard(QString board);
signals:
void Signal_InitialState();
void Signal_ClickedBoard(int board,int channel);
private:
Ui::ParticleDataStatistics *ui;
// 存储所有 DetectorStatusSummary 指针的二维数组索引从0开始
DetectorStatusSummary* m_widgetMap[MAX_BOARD][MAX_CHANNEL];
//初级粒子板卡号
int m_bd;
//初级粒子通道号
int m_ch;
};
#endif // PARTICLEDATASTATISTICS_H

View File

@ -0,0 +1,253 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ParticleDataStatistics</class>
<widget class="QWidget" name="ParticleDataStatistics">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>902</width>
<height>623</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="DetectorStatusSummary" name="widget_1_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="DetectorStatusSummary" name="widget_2_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="DetectorStatusSummary" name="widget_3_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="DetectorStatusSummary" name="widget_4_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="DetectorStatusSummary" name="widget_5_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="DetectorStatusSummary" name="widget_6_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="DetectorStatusSummary" name="widget_7_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="DetectorStatusSummary" name="widget_8_1" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="DetectorStatusSummary" name="widget_1_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="DetectorStatusSummary" name="widget_2_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="DetectorStatusSummary" name="widget_3_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="DetectorStatusSummary" name="widget_4_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="DetectorStatusSummary" name="widget_5_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="DetectorStatusSummary" name="widget_6_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="DetectorStatusSummary" name="widget_7_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="DetectorStatusSummary" name="widget_8_2" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="DetectorStatusSummary" name="widget_1_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="DetectorStatusSummary" name="widget_2_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="DetectorStatusSummary" name="widget_3_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="DetectorStatusSummary" name="widget_4_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="DetectorStatusSummary" name="widget_5_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="DetectorStatusSummary" name="widget_6_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="DetectorStatusSummary" name="widget_7_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="DetectorStatusSummary" name="widget_8_3" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="DetectorStatusSummary" name="widget_1_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="DetectorStatusSummary" name="widget_2_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="DetectorStatusSummary" name="widget_3_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="DetectorStatusSummary" name="widget_4_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="DetectorStatusSummary" name="widget_5_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="DetectorStatusSummary" name="widget_6_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="DetectorStatusSummary" name="widget_7_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="DetectorStatusSummary" name="widget_8_4" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(244, 244, 244);</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>DetectorStatusSummary</class>
<extends>QWidget</extends>
<header>DetectorStatusSummary.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,521 @@
#include "ThreeDDisplay.h"
#include "ui_ThreeDDisplay.h"
ThreeDDisplay::ThreeDDisplay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ThreeDDisplay)
{
ui->setupUi(this);
_init3DSurface();
// 初始化颜色渐变
initColorGradient();
}
ThreeDDisplay::~ThreeDDisplay()
{
delete ui;
}
void ThreeDDisplay::_init3DSurface()
{
// 连接按钮的信号槽
connect(ui->pBtn_magnify, &QPushButton::clicked, this, &ThreeDDisplay::_zoomOut);
connect(ui->pBtn_reduce, &QPushButton::clicked, this, &ThreeDDisplay::_zoomIn);
connect(ui->pBtn_restore, &QPushButton::clicked, this, &ThreeDDisplay::_resetView);
// 创建3D曲面图
m_surface = new Q3DSurface();
m_surface->setAxisX(new QValue3DAxis);
m_surface->setAxisY(new QValue3DAxis);
m_surface->setAxisZ(new QValue3DAxis);
// 设置场景和样式
m_surface->activeTheme()->setType(Q3DTheme::ThemeQt);
m_surface->setShadowQuality(QAbstract3DGraph::ShadowQualityNone);
m_surface->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRight);
// 创建数据代理和系列
m_dataProxy = new QSurfaceDataProxy();
m_series = new QSurface3DSeries(m_dataProxy);
//m_series->setDrawMode(QSurface3DSeries::DrawSurfaceAndWireframe);
m_series->setDrawMode(QSurface3DSeries::DrawSurface);//无网格线
m_series->setFlatShadingEnabled(true);
// 设置颜色渐变
QLinearGradient gradient;
gradient.setColorAt(0.0, Qt::blue);
gradient.setColorAt(0.25, Qt::cyan);
gradient.setColorAt(0.5, Qt::green);
gradient.setColorAt(0.75, Qt::yellow);
gradient.setColorAt(1.0, Qt::red);
m_series->setBaseGradient(gradient);
m_series->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
// 添加到图表
m_surface->addSeries(m_series);
// 创建容器widget
m_surfaceContainer = QWidget::createWindowContainer(m_surface, this);
//m_surfaceContainer->setMinimumSize(800, 600);
// 添加到UI布局中假设有一个QFrame或QVBoxLayout
// 这里需要根据你的实际UI布局进行调整
ui->hLayout3D->addWidget(m_surfaceContainer);
ui->hLayout3D->setContentsMargins(0, 0, 0, 0);
// 设置轴标签和标题
m_surface->axisX()->setTitle("初级粒子能量 (MeV)");
m_surface->axisY()->setTitle("符合事件计数");
m_surface->axisZ()->setTitle("次级粒子能量和 (MeV)");
// 创建自定义主题(或者修改当前主题)
Q3DTheme *customTheme = m_surface->activeTheme();
customTheme->setType(Q3DTheme::ThemeQt); // 使用Qt主题为基础
// 禁用标签边框和背景
customTheme->setLabelBorderEnabled(false); // 禁用标签边框
customTheme->setLabelBackgroundEnabled(false); // 禁用标签背景
// 设置坐标轴样式
// 保留网格线(如果需要的话),如果不想要网格线可以设为透明
// 如果希望保留淡化的网格线参考
customTheme->setGridLineColor(QColor(200, 200, 200, 50)); // 半透明灰色网格线
// 设置坐标轴标签颜色(确保标签可见)
customTheme->setLabelTextColor(Qt::black);
customTheme->setLabelBackgroundColor(Qt::transparent); // 透明背景
// 应用自定义主题
m_surface->setActiveTheme(customTheme);
// 也可以直接对坐标轴进行设置
// 设置坐标轴标签格式(可选)
m_surface->axisX()->setLabelFormat("%.1f");
m_surface->axisY()->setLabelFormat("%.0f");
m_surface->axisZ()->setLabelFormat("%.1f");
// 调整标签位置和显示
m_surface->axisX()->setLabelAutoRotation(30); // 标签适当旋转
m_surface->axisY()->setLabelAutoRotation(30);
m_surface->axisZ()->setLabelAutoRotation(30);
// 设置标题
m_surface->setTitle("符合事件能量分布曲面图");
//m_surface->setTitleFont(QFont("Arial", 20, QFont::Bold));
// 启用鼠标交互(默认已启用,这里确保设置)
m_surface->setSelectionMode(QAbstract3DGraph::SelectionNone); // 禁用选择模式,避免干扰
m_surface->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRight);// 设置初始相机位置
_saveInitialCameraState();
// 添加注释
_addAnnotations();
}
void ThreeDDisplay::_addAnnotations()
{
// 添加注释到曲面图
QCustom3DLabel* titleLabel = new QCustom3DLabel();
titleLabel->setText("符合事件分析曲面图\nX: 初级粒子能量\nY: 符合事件计数\nZ: 次级粒子能量和");
titleLabel->setFont(QFont("Arial", 12));
titleLabel->setPosition(QVector3D(0.5f, 1.0f, 0.0f));
titleLabel->setScaling(QVector3D(0.1f, 0.1f, 0.1f));
m_surface->addCustomItem(titleLabel);
}
void ThreeDDisplay::_updateSurfaceData()
{
if (m_surfaceData.isEmpty()) return;
// 准备数据数组
const int ROWS = 600 / 2; // Y轴分段数
const int COLS = 360 / 2; // X轴分段数
// 找出能量范围
float minPrimary = std::numeric_limits<float>::max();
float maxPrimary = std::numeric_limits<float>::min();
float minSecondary = std::numeric_limits<float>::max();
float maxSecondary = std::numeric_limits<float>::min();
for (const auto& point : m_surfaceData)
{
minPrimary = std::min(minPrimary, point.primaryEnergy);
maxPrimary = std::max(maxPrimary, point.primaryEnergy);
minSecondary = std::min(minSecondary, point.secondaryEnergySum);
maxSecondary = std::max(maxSecondary, point.secondaryEnergySum);
}
// 创建数据矩阵
QVector<QVector<float>> dataMatrix(ROWS, QVector<float>(COLS, 0));
// 填充数据矩阵(简单的二维直方图)
float primaryStep = (maxPrimary - minPrimary) / COLS;
float secondaryStep = (maxSecondary - minSecondary) / ROWS;
for (const auto& point : m_surfaceData)
{
int col = std::min(COLS - 1, static_cast<int>((point.primaryEnergy - minPrimary) / primaryStep));
int row = std::min(ROWS - 1, static_cast<int>((point.secondaryEnergySum - minSecondary) / secondaryStep));
if (row >= 0 && row < ROWS && col >= 0 && col < COLS)
{
dataMatrix[row][col] += point.count;
}
}
// 创建曲面数据
QSurfaceDataArray* dataArray = new QSurfaceDataArray;
dataArray->reserve(ROWS);
for (int row = 0; row < ROWS; row++)
{
QSurfaceDataRow* newRow = new QSurfaceDataRow(COLS);
float yPos = minSecondary + row * secondaryStep;
for (int col = 0; col < COLS; col++)
{
float xPos = minPrimary + col * primaryStep;
float zVal = dataMatrix[row][col]; // 计数作为高度
(*newRow)[col].setPosition(QVector3D(xPos, zVal, yPos));
}
dataArray->append(newRow);
}
// 更新代理数据
m_dataProxy->resetArray(dataArray);
// 设置轴范围
//m_surface->axisX()->setRange(minPrimary, maxPrimary);
//m_surface->axisY()->setRange(0, getMaxCount(dataMatrix));
//m_surface->axisZ()->setRange(minSecondary, maxSecondary);
if (flag)
{
qDebug()<< maxPrimary << maxSecondary;
m_surface->axisX()->setRange(0, maxPrimary);
m_surface->axisZ()->setRange(0, maxSecondary);
flag = false;
}
qDebug()<<getMaxCount(dataMatrix);
m_surface->axisY()->setRange(0, getMaxCount(dataMatrix));
}
float ThreeDDisplay::getMaxCount(const QVector<QVector<float> > &dataMatrix)
{
return 0.0;
}
void ThreeDDisplay::_saveInitialCameraState()
{
Q3DCamera *camera = m_surface->scene()->activeCamera();
m_initialCameraTarget = camera->target();
m_initialCameraXRotation = camera->xRotation();
m_initialCameraYRotation = camera->yRotation();
m_initialCameraZoomLevel = camera->zoomLevel();
}
// 缩小
void ThreeDDisplay::_zoomIn()
{
Q3DCamera *camera = m_surface->scene()->activeCamera();
float currentZoom = camera->zoomLevel();
// 减小zoomLevel可以放大视图
// zoomLevel越小视图越大
float newZoom = currentZoom - 10.0f;
// 限制最小缩放级别,避免过度放大
if (newZoom >= 10.0f)
{
camera->setZoomLevel(newZoom);
}
else
{
camera->setZoomLevel(10.0f);
}
}
// 放大
void ThreeDDisplay::_zoomOut()
{
Q3DCamera *camera = m_surface->scene()->activeCamera();
float currentZoom = camera->zoomLevel();
// 增加zoomLevel可以缩小视图
// zoomLevel越大视图越小
float newZoom = currentZoom + 10.0f;
// 限制最大缩放级别,避免过度缩小
if (newZoom <= 500.0f)
{
camera->setZoomLevel(newZoom);
}
else
{
camera->setZoomLevel(500.0f);
}
}
// 还原视图
void ThreeDDisplay::_resetView()
{
Q3DCamera *camera = m_surface->scene()->activeCamera();
// 恢复到初始的相机预设
//camera->setCameraPreset(Q3DCamera::CameraPresetIsometricRight);
//或者恢复到保存的初始状态
camera->setTarget(m_initialCameraTarget);
camera->setXRotation(m_initialCameraXRotation);
camera->setYRotation(m_initialCameraYRotation);
camera->setZoomLevel(m_initialCameraZoomLevel);
}
void ThreeDDisplay::setSurfaceData(const QVector<SurfacePoint> &surfaceData)
{
m_surfaceData = surfaceData;
_updateSurfaceData();
}
void ThreeDDisplay::setBasicParticle(double startValue, double endValue)
{
ui->lineEdit_begin_start->setText(QString::number(startValue));
ui->lineEdit_begin_end->setText(QString::number(endValue));
}
void ThreeDDisplay::setSecondParticle(double startValue, double endValue)
{
ui->lineEdit_second_start->setText(QString::number(startValue));
ui->lineEdit_second_end->setText(QString::number(endValue));
}
void ThreeDDisplay::setComplyWithEvent(double value)
{
ui->lineEdit_count->setText(QString::number(value));
}
/*--------------------设置颜色---------------------------*/
// 初始化颜色渐变
void ThreeDDisplay::initColorGradient()
{
// 设置默认渐变类型
m_gradientType = Gradient_Custom;
// 初始化颜色范围
m_colorRange.minValue = 0;
m_colorRange.maxValue = 100;
m_colorRange.range = 100.0;
//// 初始化颜色
//m_gradientColors.clear();
//m_gradientColors << QColor("#0E508A") // 蓝色
// << QColor("#D5A914") // 亮蓝
// << QColor("#D57C14") // 青色
// << QColor("#D52A3D"); // 青绿;
//// << QColor(0, 255, 0) // 绿色
//// << QColor(128, 255, 0) // 黄绿
//// << QColor(255, 255, 0) // 黄色
//// << QColor(255, 192, 0) // 橙色
//// << QColor(255, 128, 0) // 深橙
//// << QColor(255, 0, 0); // 红色
}
// 根据数值获取颜色
QColor ThreeDDisplay::getColorForValue(int value)
{
if (m_colorRange.range < 1e-6) {
return QColor("#0E508A"); // 默认蓝色
}
// 计算归一化比例 (0.0 - 1.0)
double ratio = static_cast<double>(value - m_colorRange.minValue) / m_colorRange.range;
ratio = qBound(0.0, ratio, 1.0);
// 根据渐变类型返回颜色
switch (m_gradientType) {
case Gradient_HeatMap:
return getHeatMapColor(ratio);
case Gradient_BlueToRed:
return getBlueToRedColor(ratio);
case Gradient_GreenToRed:
return getGreenToRedColor(ratio);
case Gradient_TrafficLight:
return getTrafficLightColor(ratio);
case Gradient_Custom:
return getCustomColor(ratio);
default:
return getHeatMapColor(ratio);
}
}
// 热力图颜色
QColor ThreeDDisplay::getHeatMapColor(double ratio)
{
if (m_gradientColors.isEmpty()) {
return QColor("#0E508A");
}
int colorCount = m_gradientColors.size();
double colorStep = 1.0 / (colorCount - 1);
int colorIndex = static_cast<int>(ratio / colorStep);
colorIndex = qMin(colorIndex, colorCount - 2);
double colorRatio = (ratio - colorIndex * colorStep) / colorStep;
const QColor& color1 = m_gradientColors[colorIndex];
const QColor& color2 = m_gradientColors[colorIndex + 1];
return QColor(
color1.red() + (color2.red() - color1.red()) * colorRatio,
color1.green() + (color2.green() - color1.green()) * colorRatio,
color1.blue() + (color2.blue() - color1.blue()) * colorRatio
);
}
// 蓝到红渐变
QColor ThreeDDisplay::getBlueToRedColor(double ratio)
{
// 蓝(0,0,255) -> 紫(128,0,128) -> 红(255,0,0)
if (ratio < 0.5) {
double r = ratio / 0.5;
return QColor(
static_cast<int>(128 * r), // R: 0->128
0, // G: 0
255 - static_cast<int>(127 * r) // B: 255->128
);
}
else {
double r = (ratio - 0.5) / 0.5;
return QColor(
128 + static_cast<int>(127 * r), // R: 128->255
0, // G: 0
128 - static_cast<int>(128 * r) // B: 128->0
);
}
}
// 绿到红渐变
QColor ThreeDDisplay::getGreenToRedColor(double ratio)
{
// 绿(0,255,0) -> 黄(255,255,0) -> 红(255,0,0)
if (ratio < 0.5) {
double r = ratio / 0.5;
return QColor(
static_cast<int>(255 * r), // R: 0->255
255, // G: 255
0 // B: 0
);
}
else {
double r = (ratio - 0.5) / 0.5;
return QColor(
255, // R: 255
255 - static_cast<int>(255 * r), // G: 255->0
0 // B: 0
);
}
}
// 红黄绿三色
QColor ThreeDDisplay::getTrafficLightColor(double ratio)
{
if (ratio < 0.33) {
return QColor(0, 255, 0); // 绿色
}
else if (ratio < 0.66) {
return QColor(255, 255, 0); // 黄色
}
else {
return QColor(255, 0, 0); // 红色
}
}
// 自定义
QColor ThreeDDisplay::getCustomColor(double ratio)
{
if (ratio < 0.05)
{
return QColor("#0E508A");
}
else if (ratio < 0.10)
{
return QColor("#1A7ED6");
}
else if (ratio < 0.15)
{
return QColor("#125997");
}
else if (ratio < 0.20)
{
return QColor("#1B66A7");
}
else if (ratio < 0.25)
{
return QColor("#4CA9F9");
}
else if (ratio < 0.30)
{
return QColor("#D5A914");
}
else if (ratio < 0.35)
{
return QColor("#F4C422");
}
else if (ratio < 0.40)
{
return QColor("#EBC236");
}
else if (ratio < 0.45)
{
return QColor("#EFC32F");
}
else if (ratio < 0.50)
{
return QColor("#FFF8D2");
}
else if (ratio < 0.55)
{
return QColor("#D57C14");
}
else if (ratio < 0.60)
{
return QColor("#EF9B39");
}
else if (ratio < 0.65)
{
return QColor("#F09B38");
}
else if (ratio < 0.70)
{
return QColor("#EF9831");
}
else if (ratio < 0.75)
{
return QColor("#FFECD1");
}
else if (ratio < 0.80)
{
return QColor("#D52A3D");
}
else if (ratio < 0.85)
{
return QColor("#FF334C");
}
else if (ratio < 0.90)
{
return QColor("#F55B5B");//
}
else if (ratio < 0.95)
{
return QColor("#E93E51");
}
else
{
return QColor("#FFD4D7");
}
}

View File

@ -0,0 +1,112 @@
#ifndef THREEDDISPLAY_H
#define THREEDDISPLAY_H
#include <QWidget>
#include <QtDataVisualization>
#include <QLabel>
#include "CoincidenceSpectrumProcess.h"
using namespace QtDataVisualization;
//// 用于存储三维数据
//typedef struct SurfacePoint {
// float primaryEnergy; // 初级粒子能量
// float secondaryEnergySum; // 次级粒子能量和
// int count; // 符合事件计数
//}SURFACEPOINT;
namespace Ui {
class ThreeDDisplay;
}
class ThreeDDisplay : public QWidget
{
Q_OBJECT
public:
explicit ThreeDDisplay(QWidget *parent = nullptr);
~ThreeDDisplay();
void setSurfaceData(const QVector<SurfacePoint> &surfaceData);
//设置初级粒子范围
void setBasicParticle(double startValue,double endValue);
//设置次级粒子范围
void setSecondParticle(double startValue,double endValue);
//设置符合事件计数
void setComplyWithEvent(double value);
//设置曲面图数据
private:
void _init3DSurface();
void _addAnnotations();
void _updateSurfaceData();
float getMaxCount(const QVector<QVector<float>>& dataMatrix);
// 保存初始相机状态
void _saveInitialCameraState();
// 缩小
void _zoomIn();
// 放大
void _zoomOut();
// 还原视图
void _resetView();
void initColorGradient();
// 颜色渐变管理
void updateWidgetColors(QString board); // 更新所有widget的颜色
QColor getColorForValue(int value); // 根据数值获取颜色
void updateColorRange(); // 更新颜色范围
// 颜色获取函数(不同渐变方案)
QColor getHeatMapColor(double ratio); // 热力图颜色
QColor getBlueToRedColor(double ratio); // 蓝到红渐变
QColor getGreenToRedColor(double ratio); // 绿到红渐变
QColor getTrafficLightColor(double ratio); // 红黄绿三色
QColor getCustomColor(double ratio); // 自定义
// 高亮管理
void highlightSelectedDetector(const QString& selectedName = "");
private:
Ui::ThreeDDisplay *ui;
Q3DSurface* m_surface = nullptr;
QSurfaceDataProxy* m_dataProxy = nullptr;
QSurface3DSeries* m_series = nullptr;
QWidget* m_surfaceContainer = nullptr;
// 用于保存初始相机状态
QVector3D m_initialCameraTarget;
float m_initialCameraXRotation;
float m_initialCameraYRotation;
float m_initialCameraZoomLevel;
bool flag = true;
QVector<SurfacePoint> m_surfaceData;
// 颜色渐变相关
struct ColorRange {
int minValue;
int maxValue;
double range;
};
ColorRange m_colorRange;
bool m_useGradient = true;
// 渐变颜色配置
enum GradientType {
Gradient_HeatMap, // 热力图(蓝->青->绿->黄->红)
Gradient_BlueToRed, // 蓝到红
Gradient_GreenToRed, // 绿到红
Gradient_TrafficLight, // 红黄绿
Gradient_Custom //自定义
};
GradientType m_gradientType = Gradient_Custom;
QVector<QColor> m_gradientColors;
// 颜色图例
QLabel* m_colorLegendLabel = nullptr;
};
#endif // THREEDDISPLAY_H

View File

@ -0,0 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ThreeDDisplay</class>
<widget class="QWidget" name="ThreeDDisplay">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>443</width>
<height>729</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,15,6">
<property name="spacing">
<number>10</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QPushButton" name="pBtn_restore">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>还原</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pBtn_magnify">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>放大</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pBtn_reduce">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>缩小</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>498</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<layout class="QHBoxLayout" name="hLayout3D"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,0,2,0,2,0,2">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>40</number>
</property>
<item>
<widget class="QWidget" name="widget_6" native="true">
<property name="styleSheet">
<string notr="true">QWidget#widget_6{
border-bottom: 1px solid #1763a2;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="topMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<item>
<widget class="QLabel" name="label_5">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>选择的符合事件相关信息展示:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>初级粒子能量范围:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_begin_start"/>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>~</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_begin_end"/>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>keV</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLabel" name="label_10">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>次级粒子能量范围:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_second_start"/>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>~</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_second_end"/>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>keV</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLabel" name="label_12">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>符合事件计数:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_count"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>120</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>