DiagramDesigner/diagramCavas/source/monitorAttributeGroupDlg.cpp

341 lines
11 KiB
C++
Raw 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.

#include "monitorAttributeGroupDlg.h"
#include "monitorAttributeDlg.h"
#include "monitorSideBarDlg.h"
#include "monitorPanel.h"
#include "monitorDetailAttributeDlg.h"
#include <QScrollArea>
#include <QFormLayout>
#include <QLabel>
#include <QUuid>
#include <QChartView>
#include <QBarSeries>
#include <QBarCategoryAxis>
#include <QValueAxis>
#include <QLineSeries>
#include <QDateTimeAxis>
#include "global.h"
MonitorAttributeGroupDlg::MonitorAttributeGroupDlg(QWidget* parent)
: QScrollArea(parent)
,_layout(nullptr)
,_pParent(nullptr)
,_pDetailParent(nullptr)
,_curMode(0)
{
initial();
}
MonitorAttributeGroupDlg::~MonitorAttributeGroupDlg()
{
}
void MonitorAttributeGroupDlg::initial()
{
_layout = new QVBoxLayout(this);
}
void MonitorAttributeGroupDlg::createGroupView(QList<monitorItemAttributeInfo> lst,int nType)
{
QWidget* content = new QWidget();
QGridLayout* gridLayout = new QGridLayout(content);
gridLayout->setHorizontalSpacing(2);
gridLayout->setVerticalSpacing(10);
gridLayout->setContentsMargins(0, 0, 0, 0);
// 设置列的最小宽度和拉伸比例
gridLayout->setColumnMinimumWidth(0, 30); // 标签列最小宽度
gridLayout->setColumnStretch(0, 1); // 标签列拉伸因子
gridLayout->setColumnStretch(1, 8); // 控件列拉伸因子
int row = 0;
for(auto& info : lst) {
QLabel* label = new QLabel(info.sTag, this);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
label->setMaximumWidth(40); // 设置标签最大宽度
QWidget* editor = createEditor(info);
editor->setProperty("category", info.nShowType);
editor->setProperty("graphType", info.nGraphType);
editor->setProperty("connectPara", info.sConnectPara);
// 添加到网格布局
gridLayout->addWidget(label, row, 0, Qt::AlignRight | Qt::AlignVCenter);
gridLayout->addWidget(editor, row, 1);
// 设置行的拉伸因子(可选)
gridLayout->setRowStretch(row, 0); // 不拉伸,保持内容高度
_curWidget.insert(info.sTag, editor);
row++;
}
// 添加一个拉伸行,使内容在顶部对齐
gridLayout->setRowStretch(row, 1);
setWidget(content);
setWidgetResizable(true);
}
QWidget* MonitorAttributeGroupDlg::createEditor(monitorItemAttributeInfo info,int nType)
{
QWidget* pWidget = nullptr;
if(info.nShowType == 0){ //正常显示
QLabel *label = new QLabel(this);
pWidget = label;
}
else{ //图表
QChartView* chartView = new QChartView(this);
QSize size;
if(nType == 0)
size = QSize(400,300);
else
size = QSize(600,400);
chartView->setMinimumSize(size);
chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
chartView->setRenderHint(QPainter::Antialiasing);
QChart* chart = new QChart();
chartView->setChart(chart);
if (info.nGraphType == 0) {
// 创建折线序列
QLineSeries* series = new QLineSeries();
QFont axisFont;
axisFont.setPointSize(9);
// 创建图表
chart->addSeries(series);
chart->setTitle(info.sName);
chart->setAnimationOptions(QChart::SeriesAnimations);
// 设置线条样式
QPen pen(Qt::blue);
pen.setWidth(3);
pen.setStyle(Qt::SolidLine);
series->setPen(pen);
// 创建坐标轴
QValueAxis* axisX = new QValueAxis();
QValueAxis* axisY = new QValueAxis();
// 添加坐标轴到图表
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
// 将序列关联到坐标轴
series->attachAxis(axisX);
series->attachAxis(axisY);
// 设置默认范围或等待数据更新
axisX->setRange(0, 10); // 临时范围
axisY->setRange(0, 100);
// 设置坐标轴标题
axisX->setTitleText("时间");
axisX->setLabelsFont(axisFont);
axisX->setTitleFont(axisFont);
axisY->setTitleText("");
axisY->setLabelsFont(axisFont);
axisY->setTitleFont(axisFont);
chart->setTheme(QChart::ChartThemeLight);
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
QFont legendFont = chart->legend()->font();
legendFont.setPointSize(9); // 设置图例字体大小
chart->legend()->setFont(legendFont);
}
else if (info.nGraphType == 1) {
QBarSeries* series = new QBarSeries();
chart->addSeries(series);
chart->setTitle(info.sName);
chart->setAnimationOptions(QChart::SeriesAnimations);
// 创建坐标轴
QBarCategoryAxis* axisX = new QBarCategoryAxis();
QValueAxis* axisY = new QValueAxis();
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisX);
series->attachAxis(axisY);
}
pWidget = chartView;
}
return pWidget;
}
void MonitorAttributeGroupDlg::updateLineChartData(QChartView* chartView, const QVector<QPointF>& data)
{
if (!chartView || data.isEmpty()) return;
QChart* chart = chartView->chart();
if (!chart) {
chart = new QChart();
chart->setAnimationOptions(QChart::NoAnimation);
chartView->setChart(chart);
}
QLineSeries* series = nullptr;
if (chart->series().isEmpty()) {
series = new QLineSeries();
chart->addSeries(series);
} else {
series = qobject_cast<QLineSeries*>(chart->series().first());
if (!series) return;
}
series->clear();
// 计算数据范围
qint64 minTime = std::numeric_limits<qint64>::max();
qint64 maxTime = std::numeric_limits<qint64>::lowest();
double minVal = std::numeric_limits<double>::max();
double maxVal = std::numeric_limits<double>::lowest();
for (const QPointF& point : data) {
qint64 t = static_cast<qint64>(point.x());
series->append(t, point.y());
minTime = qMin(minTime, t);
maxTime = qMax(maxTime, t);
minVal = qMin(minVal, point.y());
maxVal = qMax(maxVal, point.y());
}
// ========== 简单直接的方法:确保只有一个坐标轴 ==========
QDateTimeAxis* xAxis = nullptr;
QValueAxis* yAxis = nullptr;
// 获取当前所有坐标轴
QList<QAbstractAxis*> allAxes = chart->axes();
// 如果坐标轴太多,清理所有
//if (allAxes.size() > 2) { // 应该只有x轴和y轴
for (auto axis : allAxes) {
chart->removeAxis(axis);
delete axis;
}
allAxes.clear();
//}
// 在剩余的坐标轴中查找
for (auto axis : allAxes) {
if (!xAxis && qobject_cast<QDateTimeAxis*>(axis)) {
xAxis = qobject_cast<QDateTimeAxis*>(axis);
} else if (!yAxis && qobject_cast<QValueAxis*>(axis)) {
yAxis = qobject_cast<QValueAxis*>(axis);
}
}
// 创建缺失的坐标轴
if (!xAxis) {
xAxis = new QDateTimeAxis();
xAxis->setTitleText("时间");
chart->addAxis(xAxis, Qt::AlignBottom);
}
if (!yAxis) {
yAxis = new QValueAxis();
yAxis->setTitleText("");
chart->addAxis(yAxis, Qt::AlignLeft);
}
// 确保系列附加
series->attachAxis(xAxis);
series->attachAxis(yAxis);
// 设置范围和其他属性
qint64 timeMargin = qMax<qint64>((maxTime - minTime) * 0.05, 1000);
double valMargin = qMax((maxVal - minVal) * 0.1, 0.1);
xAxis->setRange(
QDateTime::fromMSecsSinceEpoch(minTime - timeMargin),
QDateTime::fromMSecsSinceEpoch(maxTime + timeMargin)
);
yAxis->setRange(minVal - valMargin, maxVal + valMargin);
qint64 timeSpan = maxTime - minTime;
xAxis->setFormat((timeSpan > 3600000) ? "HH:mm:ss" : "HH:mm:ss.zzz");
xAxis->setTickCount(6);
yAxis->setTickCount(8);
yAxis->setLabelFormat("%.2f");
QFont font;
font.setPointSize(9);
xAxis->setLabelsFont(font);
yAxis->setLabelsFont(font);
}
void MonitorAttributeGroupDlg::updateData()
{
if(_pParent || _pDetailParent){
auto pModel = getModelController();
auto pMap = pModel->getMonitorPara();
QUuid uid = getCurUid();
if(!pMap.isEmpty() && pMap.contains(uid)){
auto info = pMap.value(uid);
for(auto &widget:_curWidget){
int nCate = widget->property("category").toInt();
int nGraph = widget->property("graphType").toInt();
QString sPara = widget->property("connectPara").toString();
for(auto& data:info){
if(data.sConnectPara == sPara){
if(nCate == 0){
QLabel* pLabel = dynamic_cast<QLabel*>(widget);
pLabel->setText(QString::number(data.mapValue.last()));
}
else{
if(nGraph == 0){ //折线图
// 转换为 QVector<QPointF>
QVector<QPointF> points;
points.reserve(data.mapValue.size()); // 预分配内存以提高性能
// 遍历 QMap
for (auto it = data.mapValue.constBegin(); it != data.mapValue.constEnd(); ++it) {
// 将 quint64 时间戳转换为 qrealQPointF 使用 qreal
qint64 timestampMs = it.key() / 1000000; // 纳秒转毫秒
points.append(QPointF(static_cast<qreal>(timestampMs), it.value()));
}
QChartView* pView = dynamic_cast<QChartView*>(widget);
updateLineChartData(pView,points);
}
else if(nGraph == 1){
}
}
}
}
}
}
}
}
FixedPortsModel* MonitorAttributeGroupDlg::getModelController()
{
FixedPortsModel* pModel;
if(_curMode == 0){
pModel = _pParent->getParent()->getParent()->getModelController();
}
else{
pModel = _pDetailParent->getParent()->getModelController();
}
return pModel;
}
QUuid MonitorAttributeGroupDlg::getCurUid()
{
if(_curMode == 0){
return _pParent->getCurId();
}
else{
return _pDetailParent->getCurId();
}
}