XNSim/XNMonitor/ModelStatusWidget/ModelStatusWidget.cpp
2025-04-28 12:25:20 +08:00

681 lines
24 KiB
C++
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file ModelStatusWidget.cpp
* @author jinchao
* @brief 模型状态窗口实现
* @version 1.0
* @date 2025-03-10
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#include "ModelStatusWidget.h"
#include <QHBoxLayout>
#include <QScrollArea>
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QTableWidget>
#include <QHeaderView>
#include "../XNCustomPlot.h"
ModelStatusWidget::ModelStatusWidget(QWidget *parent, SystemStatusWidget *systemStatusWidget)
: QWidget(parent)
{
//初始化系统运行状态窗口指针
this->systemStatusWidget = systemStatusWidget;
//初始化模型状态标签页
setupTabModelStatus();
//初始化模型信息线程
InitialModelInfoThread();
}
ModelStatusWidget::~ModelStatusWidget()
{
//释放模型信息线程
if (modelThread != nullptr) {
modelThread->onThreadQuit();
modelThread->quit();
modelThread->wait();
delete modelThread;
modelThread = nullptr;
}
}
void ModelStatusWidget::onSetCurrentTabIndex(int index)
{
this->currentTabIndex = index;
if (currentTabIndex == 1) {
//如果当前选中的标签页为1则显示模型状态窗口
this->show();
//控制模型信息线程
emit controlModelInfoThread(true);
} else {
//如果当前选中的标签页为0则隐藏模型状态窗口
this->hide();
//控制模型信息线程
emit controlModelInfoThread(false);
}
}
void ModelStatusWidget::InitialModelInfoThread()
{
//初始化模型信息线程
modelThread = new ModelInfoUpdateThread(this);
//连接模型信息线程的更新模型信息信号到槽函数
connect(modelThread, &ModelInfoUpdateThread::updateModelInfo, this,
&ModelStatusWidget::updateModelData);
//连接模型信息线程的控制信号到槽函数
connect(this, &ModelStatusWidget::controlModelInfoThread, modelThread,
&ModelInfoUpdateThread::onThreadController);
//初始化模型信息线程
modelThread->Initialize();
//启动模型信息线程
modelThread->start();
}
// 设置模型状态标签页
void ModelStatusWidget::setupTabModelStatus()
{
QHBoxLayout *mainLayout = new QHBoxLayout(this); // 创建水平布局
// 使用QSplitter进行左右栏的动态分割
QSplitter *horizontalSplitter = new QSplitter(Qt::Horizontal); // 创建一个水平方向的QSplitter
// 左栏布局
setupTabModelStatusLeftPanel(horizontalSplitter);
// 右栏布局
setupTabModelStatusRightPanel(horizontalSplitter);
// 设置QSplitter的初始分割比例为1:4即左栏占五分之一右栏占五分之四
QList<int> sizes;
sizes << 1 << 4;
horizontalSplitter->setSizes(sizes);
// 将QSplitter添加到主布局中
mainLayout->addWidget(horizontalSplitter);
}
// 设置模型状态左栏的布局和组件
void ModelStatusWidget::setupTabModelStatusLeftPanel(QSplitter *splitter)
{
// 左栏布局
QVBoxLayout *leftMainLayout = new QVBoxLayout();
QWidget *leftMainWidget = new QWidget();
leftMainLayout->addWidget(leftMainWidget);
QVBoxLayout *leftLayout = new QVBoxLayout();
leftLayout->setObjectName("ModelStatusLeftLayout");
leftMainWidget->setLayout(leftLayout);
leftMainLayout->addStretch(); // 添加一个伸展项,使得布局可以自动调整大小
// 创建一个QWidget作为左栏的容器并设置其布局为leftLayout
QWidget *leftPanel = new QWidget();
leftPanel->setLayout(leftMainLayout);
// 创建一个QScrollArea来包含左栏的布局
QScrollArea *leftScrollArea = new QScrollArea(this);
leftScrollArea->setWidget(leftPanel);
leftScrollArea->setWidgetResizable(true);
leftScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
leftScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// 将QScrollArea添加到QSplitter中
splitter->addWidget(leftScrollArea);
}
// 创建线程信息页面
QWidget *ModelStatusWidget::createThreadInfoPage(unsigned int threadIndex)
{
QWidget *page = new QWidget();
QGridLayout *gridLayout = new QGridLayout(page);
// 定义运行信息的标签和初始值
// 定义标签列表
const QStringList labels = {"线程ID", "运行状态", "运行周期数", "实时频率", "设定频率",
"最小频率", "最大频率", "平均频率", "实时周期", "设定周期",
"最小周期", "最大周期", "平均周期"};
// 定义值列表
const QStringList values = {"0", "未运行", "0", "0Hz", "0Hz", "0Hz", "0Hz",
"0Hz", "0ms", "0ms", "0ms", "0ms", "0ms"};
// 遍历标签和值列表为每个条目创建两个QLabel
for (int i = 0; i < labels.size(); ++i) {
QLabel *label = new QLabel(labels[i], page);
QLabel *valueLabel = new QLabel(values[i], page);
// 设置QLabel的对齐方式
// 设置标签对齐方式为左对齐
label->setAlignment(Qt::AlignLeft);
// 设置值标签对齐方式为右对齐
valueLabel->setAlignment(Qt::AlignRight);
// 设置valueLabel的objectName以便后续可以通过findChild找到并更新它
valueLabel->setObjectName(QString("threadRunValueLabel%1_%2").arg(threadIndex).arg(i));
// 将QLabel添加到网格布局中
// 在第i行第0列放置标签
gridLayout->addWidget(label, i, 0);
// 在第i行第1列放置值
gridLayout->addWidget(valueLabel, i, 1);
}
return page;
}
// 切换线程信息页面的显示状态
void ModelStatusWidget::toggleThreadInfo()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
if (button) {
QString buttonText = button->objectName();
int threadIndex = extractTrailingNumbers(buttonText, 3); // 提取数字部分作为线程索引
if (threadIndex < 0)
return;
QWidget *coreInfoPage = findChild<QWidget *>(QString("threadInfoPage%1").arg(threadIndex));
if (!coreInfoPage)
return;
coreInfoPage->setVisible(!coreInfoPage->isVisible());
}
}
// 设置模型状态右栏的布局和组件
void ModelStatusWidget::setupTabModelStatusRightPanel(QSplitter *splitter)
{
// 右栏布局
QVBoxLayout *rightLayout = new QVBoxLayout();
// 创建一个新的QSplitter用于垂直分割右栏的上下两部分
QSplitter *verticalSplitter = new QSplitter(Qt::Vertical); // 垂直方向的QSplitter
// 表格布局
QTableWidget *modelStatusTableWidget = new QTableWidget();
setupModelStatusTableWidget(modelStatusTableWidget);
// 图表绘制区域
QWidget *modelChartWidget = new QWidget(); // 图表区域可以使用XNCustomPlot等库进行绘制
setupModelStatusChartWidget(modelChartWidget); // 配置图表区域
// 将表格和图表添加到垂直分割器中
verticalSplitter->addWidget(modelStatusTableWidget);
verticalSplitter->addWidget(modelChartWidget);
QList<int> sizes;
sizes << 3 << 2;
verticalSplitter->setSizes(sizes);
// 将垂直分割器添加到右栏布局中
rightLayout->addWidget(verticalSplitter);
// 创建一个QWidget作为右栏的容器并设置其布局为rightLayout
QWidget *rightPanel = new QWidget();
rightPanel->setLayout(rightLayout);
// 将右栏容器添加到QSplitter中
splitter->addWidget(rightPanel);
}
// 设置模型状态表格
void ModelStatusWidget::setupModelStatusTableWidget(QTableWidget *tableWidget)
{
tableWidget->setRowCount(10); // 设置表格的行数
tableWidget->setColumnCount(15); // 设置表格的列数
QFont headerFont("Arial", 16, QFont::Bold);
tableWidget->horizontalHeader()->setFont(headerFont);
// 设置表格的列标题
tableWidget->setHorizontalHeaderLabels(
{"模型名称", "模型ID", "运行状态", "所属线程", "运行节点", "优先级", "设定频率", "最小频率",
"最大频率", "平均频率", "周期数", "设定周期", "最小周期", "最大周期", "平均周期"});
// 设置表格列宽自适应
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
// 设置表格的选择行为为按行选择
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
// 设置表格的选择模式为单选
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
// 设置表格不可编辑
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
// 设置表格的objectName以便后续可以通过findChild找到并更新它
tableWidget->setObjectName("modelStatusTableWidget");
// 连接 threadStatusTableWidget 的 itemSelectionChanged 信号到槽函数
connect(tableWidget, &QTableWidget::itemSelectionChanged, this,
&ModelStatusWidget::onModelStatusTableSelectionChanged);
}
// 处理模型状态表格的选择变化
void ModelStatusWidget::onModelStatusTableSelectionChanged()
{
if (currentTabIndex != 1)
return;
QTableWidget *modelStatusTableWidget = findChild<QTableWidget *>("modelStatusTableWidget");
if (!modelStatusTableWidget) {
return;
}
int rowIndex = modelStatusTableWidget->currentRow();
if (rowIndex < 0 || rowIndex >= modelDataVec.size()) {
return;
}
XNCustomPlot *customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
if (!customPlot)
return; // 确保找到了XNCustomPlot对象
const XNRuntimeData &data = modelDataVec[rowIndex];
QVector<double> xData, yData;
if (freqOrPeriodIndex == 0 && data.m_CurrentPeriod.size() > 0) {
customPlot->xAxis->setRange(0, data.m_CurrentPeriod.size());
customPlot->yAxis->setRange(data.m_MinPeriod - 1, data.m_MaxPeriod + 1);
for (int i = 0; i < data.m_CurrentPeriod.size(); ++i) {
xData.push_back(i);
yData.push_back(data.m_CurrentPeriod[i]);
}
} else if (freqOrPeriodIndex == 1 && data.m_CurrentFrequency.size() > 0) {
customPlot->xAxis->setRange(0, data.m_CurrentFrequency.size());
customPlot->yAxis->setRange(data.m_MinFrequency - 1, data.m_MaxFrequency + 1);
for (int i = 0; i < data.m_CurrentFrequency.size(); ++i) {
xData.push_back(i);
yData.push_back(data.m_CurrentFrequency[i]);
}
} else {
return;
}
updatePlotData(xData, yData);
}
// 设置模型状态图表
void ModelStatusWidget::setupModelStatusChartWidget(QWidget *modelStatusChartWidget)
{
modelStatusChartWidget->setObjectName("modelStatusChartWidget");
XNCustomPlot *customPlot = new XNCustomPlot(modelStatusChartWidget);
customPlot->setObjectName("modelStatusCustomPlot");
// 设置图表布局
modelStatusChartWidget->setLayout(new QVBoxLayout());
modelStatusChartWidget->layout()->addWidget(customPlot);
// 配置图表
customPlot->setBackground(QBrush(QColor("#19232D")));
customPlot->xAxis->setLabelColor(Qt::white);
customPlot->yAxis->setLabelColor(Qt::white);
customPlot->xAxis->setLabel("时间(s)");
customPlot->yAxis->setLabel("周期(ms)");
customPlot->xAxis->setTickLabelRotation(60);
customPlot->xAxis->setTickLabelColor(Qt::white);
customPlot->yAxis->setTickLabelColor(Qt::white);
customPlot->xAxis->grid()->setVisible(true);
customPlot->yAxis->grid()->setVisible(true);
// 添加图表并设置绿色
customPlot->addGraph();
QPen greenPen(Qt::green);
greenPen.setWidth(2);
customPlot->graph(0)->setPen(greenPen);
// 为chartWidget设置上下文菜单
connect(customPlot, &XNCustomPlot::customContextMenuRequested, this,
&ModelStatusWidget::showChartContextMenu);
// 连接信号
connect(this, &ModelStatusWidget::updateModelCutomPlotData, this,
&ModelStatusWidget::onModelStatusTableSelectionChanged);
customPlot->replot();
}
// 处理图表中的右键点击事件
void ModelStatusWidget::showChartContextMenu(const QPoint &pos)
{
XNCustomPlot *customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
if (!customPlot)
return; // 确保找到了XNCustomPlot对象
QMenu contextMenu(this);
QAction *actionFrequency = contextMenu.addAction("显示频率");
QAction *actionPeriod = contextMenu.addAction("显示周期");
// 连接QAction的triggered信号到相应的槽函数
connect(actionFrequency, &QAction::triggered, this, &ModelStatusWidget::onShowFrequency);
connect(actionPeriod, &QAction::triggered, this, &ModelStatusWidget::onShowPeriod);
// 在chartWidget上显示上下文菜单
QAction *selectedAction = contextMenu.exec(customPlot->mapToGlobal(pos));
}
// 处理右键菜单中的"显示频率"选项
void ModelStatusWidget::onShowFrequency()
{
XNCustomPlot *customPlot = nullptr;
if (currentTabIndex == 1) {
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
} else
return;
if (!customPlot)
return; // 确保找到了XNCustomPlot对象
// 实现显示频率的逻辑
customPlot->yAxis->setLabel("频率(Hz)");
freqOrPeriodIndex = 1;
customPlot->replot(); // 重新绘制图表以显示新数据
emit updateModelCutomPlotData();
}
// 处理右键菜单中的"显示周期"选项
void ModelStatusWidget::onShowPeriod()
{
XNCustomPlot *customPlot = nullptr;
if (currentTabIndex == 1) {
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
} else
return;
if (!customPlot)
return; // 确保找到了XNCustomPlot对象
// 实现显示周期的逻辑
customPlot->yAxis->setLabel("周期(ms)");
freqOrPeriodIndex = 0;
customPlot->replot(); // 重新绘制图表以显示新数据
emit updateModelCutomPlotData();
}
// 更新线程信息页面
void ModelStatusWidget::updateThreadInfoPage(unsigned int threadIndex, const XNRuntimeData &data)
{
if (currentTabIndex != 1)
return;
QPushButton *threadInfoButton =
findChild<QPushButton *>(QString("threadInfoButton%1").arg(threadIndex));
if (NULL == threadInfoButton) {
QVBoxLayout *leftLayout = findChild<QVBoxLayout *>("ModelStatusLeftLayout");
if (NULL == leftLayout)
return;
threadInfoButton = new QPushButton(data.m_name);
threadInfoButton->setObjectName(QString("threadInfoButton%1").arg(threadIndex));
connect(threadInfoButton, &QPushButton::clicked, this,
&ModelStatusWidget::toggleThreadInfo);
leftLayout->addWidget(threadInfoButton);
QWidget *threadInfoPage = createThreadInfoPage(threadIndex);
threadInfoPage->setObjectName(QString("threadInfoPage%1").arg(threadIndex));
leftLayout->addWidget(threadInfoPage);
}
threadInfoButton->setText(data.m_name);
QWidget *threadInfoPage = findChild<QWidget *>(QString("threadInfoPage%1").arg(threadIndex));
if (threadInfoPage) {
updateThreadInfoValue(threadIndex, 0, QString::number(data.m_id));
switch (data.m_RunningState) {
case 0:
updateThreadInfoValue(threadIndex, 1, "未运行");
break;
case 1:
updateThreadInfoValue(threadIndex, 1, "运行中");
break;
case 2:
updateThreadInfoValue(threadIndex, 1, "暂停中");
break;
case 3:
updateThreadInfoValue(threadIndex, 1, "错误");
break;
default:
updateThreadInfoValue(threadIndex, 1, "未知状态");
break;
}
updateThreadInfoValue(threadIndex, 2, QString::number(data.m_CycleCount));
updateThreadInfoValue(
threadIndex, 3,
QString("%1 Hz").arg(data.m_CurrentFrequency[data.m_CurrentFrequency.size() - 1], 0,
'f', 2));
updateThreadInfoValue(threadIndex, 4, QString("%1 Hz").arg(data.m_SetFrequency, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 5, QString("%1 Hz").arg(data.m_MinFrequency, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 6, QString("%1 Hz").arg(data.m_MaxFrequency, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 7, QString("%1 Hz").arg(data.m_AvgFrequency, 0, 'f', 2));
updateThreadInfoValue(
threadIndex, 8,
QString("%1 ms").arg(data.m_CurrentPeriod[data.m_CurrentPeriod.size() - 1], 0, 'f', 2));
updateThreadInfoValue(threadIndex, 9, QString("%1 ms").arg(data.m_SetPeriod, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 10, QString("%1 ms").arg(data.m_SetPeriod, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 11, QString("%1 ms").arg(data.m_MaxPeriod, 0, 'f', 2));
updateThreadInfoValue(threadIndex, 12, QString("%1 ms").arg(data.m_AvgPeriod, 0, 'f', 2));
}
}
// 更新线程信息值
void ModelStatusWidget::updateThreadInfoValue(unsigned int threadIndex, int index,
const QString &newValue)
{
if (currentTabIndex != 1)
return;
QLabel *valueLabel =
findChild<QLabel *>(QString("threadRunValueLabel%1_%2").arg(threadIndex).arg(index));
if (valueLabel) {
valueLabel->setText(newValue);
if (1 == index) {
if (newValue == "未运行") {
valueLabel->setStyleSheet("color: gray;");
} else if (newValue == "运行中") {
valueLabel->setStyleSheet("color: green;");
} else if (newValue == "暂停中") {
valueLabel->setStyleSheet("color: orange;");
} else if (newValue == "错误") {
valueLabel->setStyleSheet("color: red;");
} else {
valueLabel->setText("未知状态");
valueLabel->setStyleSheet("color: red;");
}
}
}
}
// 更新图表数据
void ModelStatusWidget::updatePlotData(const QVector<double> &newXData,
const QVector<double> &newYData)
{
XNCustomPlot *customPlot = nullptr;
if (currentTabIndex == 1)
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
else if (currentTabIndex == 2)
customPlot = findChild<XNCustomPlot *>("dataMonitoringCustomPlot");
else
return;
if (!customPlot)
return; // 确保找到了XNCustomPlot对象
if (customPlot->graphCount() == 1) {
// 假设我们只有一个图形
customPlot->graph(0)->setData(newXData, newYData);
customPlot->replot(); // 重新绘制图表以显示新数据
} else {
customPlot->addGraph(); // 添加一个新的图形
customPlot->graph(0)->setData(newXData, newYData);
customPlot->replot(); // 重新绘制图表以显示新数据
}
}
// 更新模型数据
void ModelStatusWidget::updateModelData(const XNRuntimeData &data)
{
// 如果当前标签页不是第二个,则直接返回
if (currentTabIndex != 1)
return;
// 遍历 modelDataVec 向量
for (size_t i = 0; i < modelDataVec.size(); i++) {
// 如果当前遍历到的元素 ID 与传入数据的 ID 相同
if (data.m_id == modelDataVec[i].m_id) {
double currectFrequency = data.m_CurrentFrequency[0]; // 当前频率
double currentPeriod = data.m_CurrentPeriod[0]; // 当前周期
// 更新模型运行状态
modelDataVec[i].m_RunningState = data.m_RunningState;
// 如果模型不是运行状态,则不更新频率和周期数据
if (data.m_RunningState != 1)
return;
// 更新当前频率
modelDataVec[i].m_CurrentFrequency.push_back(currectFrequency);
// 更新当前周期
modelDataVec[i].m_CurrentPeriod.push_back(currentPeriod);
// 更新周期计数
modelDataVec[i].m_CycleCount = data.m_CycleCount;
// 更新最小频率
modelDataVec[i].m_MinFrequency =
std::min(currectFrequency, modelDataVec[i].m_MinFrequency);
// 更新最大频率
modelDataVec[i].m_MaxFrequency =
std::max(currectFrequency, modelDataVec[i].m_MaxFrequency);
// 更新平均频率
modelDataVec[i].m_AvgFrequency =
((data.m_CycleCount - 1) * modelDataVec[i].m_AvgFrequency + currectFrequency)
/ data.m_CycleCount;
// 更新最小周期
modelDataVec[i].m_MinPeriod = std::min(currentPeriod, modelDataVec[i].m_MinPeriod);
// 更新最大周期
modelDataVec[i].m_MaxPeriod = std::max(currentPeriod, modelDataVec[i].m_MaxPeriod);
// 更新平均周期
modelDataVec[i].m_AvgPeriod =
((data.m_CycleCount - 1) * modelDataVec[i].m_AvgPeriod + currentPeriod)
/ data.m_CycleCount;
// 如果当前频率或周期向量的长度超过100移除最前面的元素
if (modelDataVec[i].m_CurrentFrequency.size() > 100) {
modelDataVec[i].m_CurrentFrequency.pop_front();
modelDataVec[i].m_CurrentPeriod.pop_front();
}
// 检查当前选中的行是否是被更新的行
// 找到名为 "modelStatusTableWidget" 的子控件
QTableWidget *modelStatusTableWidget =
findChild<QTableWidget *>("modelStatusTableWidget");
if (modelStatusTableWidget) {
int currentRow = modelStatusTableWidget->currentRow();
if (currentRow == static_cast<int>(i)) {
emit updateModelCutomPlotData();
}
}
// 更新表格数据
updateModelTableData(modelDataVec[i], i);
return;
}
}
// 如果未找到匹配的 ID将传入的数据添加到 modelDataVec 向量末尾
modelDataVec.push_back(data);
// 更新表格数据
updateModelTableData(data, modelDataVec.size() - 1);
}
// 更新模型表格数据
void ModelStatusWidget::updateModelTableData(const XNRuntimeData &data, int rowIndex)
{
// 如果当前标签页索引不为1则直接返回
if (currentTabIndex != 1)
return;
// 查找名为"threadStatusTableWidget"的QTableWidget
QTableWidget *modelStatusTableWidget = findChild<QTableWidget *>("modelStatusTableWidget");
if (!modelStatusTableWidget) {
// 如果没有找到,则直接返回
return;
}
// 设置表格的行数
modelStatusTableWidget->setRowCount(std::max(rowIndex + 1, (int)modelDataVec.size()));
// 设置模型名称
modelStatusTableWidget->setItem(rowIndex, 0, new QTableWidgetItem(data.m_name));
// 设置模型ID
modelStatusTableWidget->setItem(rowIndex, 1, new QTableWidgetItem(QString::number(data.m_id)));
// 根据模型的运行状态设置不同的状态显示
switch (data.m_RunningState) {
case 0:
// 未运行状态
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未运行"));
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::gray));
break;
case 1:
// 运行中状态
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("运行中"));
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::green));
break;
case 2:
// 暂停中状态
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("暂停中"));
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::yellow));
break;
default:
// 未知状态
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未知状态"));
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::red));
break;
}
// 设置所属线程
if (systemStatusWidget != nullptr) {
modelStatusTableWidget->setItem(
rowIndex, 3,
new QTableWidgetItem(systemStatusWidget->getThreadName(data.m_AffinityMask)));
} else {
modelStatusTableWidget->setItem(rowIndex, 3, new QTableWidgetItem("未知线程"));
}
// 设置节点号
modelStatusTableWidget->setItem(rowIndex, 4,
new QTableWidgetItem(QString::number(data.m_NodeID)));
// 设置模型优先级
modelStatusTableWidget->setItem(rowIndex, 5,
new QTableWidgetItem(QString::number(data.m_Priority)));
// 设置模型设置频率
modelStatusTableWidget->setItem(
rowIndex, 6, new QTableWidgetItem(QString::number(data.m_SetFrequency, 'f', 2) + " Hz"));
// 设置模型最小频率
modelStatusTableWidget->setItem(
rowIndex, 7, new QTableWidgetItem(QString::number(data.m_MinFrequency, 'f', 2) + " Hz"));
// 设置模型最大频率
modelStatusTableWidget->setItem(
rowIndex, 8, new QTableWidgetItem(QString::number(data.m_MaxFrequency, 'f', 2) + " Hz"));
// 设置模型平均频率
modelStatusTableWidget->setItem(
rowIndex, 9, new QTableWidgetItem(QString::number(data.m_AvgFrequency, 'f', 2) + " Hz"));
// 设置模型周期计数
modelStatusTableWidget->setItem(rowIndex, 10,
new QTableWidgetItem(QString::number(data.m_CycleCount)));
// 设置模型设置周期
modelStatusTableWidget->setItem(
rowIndex, 11, new QTableWidgetItem(QString::number(data.m_SetPeriod, 'f', 2) + " ms"));
// 设置模型最小周期
modelStatusTableWidget->setItem(
rowIndex, 12, new QTableWidgetItem(QString::number(data.m_MinPeriod, 'f', 2) + " ms"));
// 设置模型最大周期
modelStatusTableWidget->setItem(
rowIndex, 13, new QTableWidgetItem(QString::number(data.m_MaxPeriod, 'f', 2) + " ms"));
// 设置模型平均周期
modelStatusTableWidget->setItem(
rowIndex, 14, new QTableWidgetItem(QString::number(data.m_AvgPeriod, 'f', 2) + " ms"));
}
// 提取字符串末尾的数字
int ModelStatusWidget::extractTrailingNumbers(const QString &str, int count)
{
QRegularExpression re("\\d{1," + QString::number(count) + "}$");
QRegularExpressionMatch match = re.match(str);
if (match.hasMatch()) {
return match.captured().toInt();
} else {
return -1; // 如果没有找到匹配项,则返回一个-1
}
}