From 3e6cd36162fcaf2890d34e6d69b65fd3010386e1 Mon Sep 17 00:00:00 2001 From: duanshengchao <519970194@qq.com> Date: Fri, 5 Sep 2025 14:54:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90=E7=9B=B4=E6=96=B9?= =?UTF-8?q?=E5=9B=BE=E6=95=B0=E6=8D=AE=E7=9A=84=E5=8A=A8=E6=80=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dataPanel/dpBarsChart.cpp | 107 +++++++++++++++++++++------- dataPanel/dpBarsChart.h | 5 +- dataPanel/dpConfigurationDialog.cpp | 8 ++- dataPanel/dpGlobals.h | 4 +- dataPanel/dpLineChart.cpp | 79 +++++++++++++++++++- dataPanel/dpLineChart.h | 2 +- source/dataManager.cpp | 3 +- ui/dpConfigurationDialog.ui | 6 +- 8 files changed, 178 insertions(+), 36 deletions(-) diff --git a/dataPanel/dpBarsChart.cpp b/dataPanel/dpBarsChart.cpp index bb68a43..7829a4c 100644 --- a/dataPanel/dpBarsChart.cpp +++ b/dataPanel/dpBarsChart.cpp @@ -3,11 +3,17 @@ CustomBars::CustomBars(QCPAxis* keyAxis, QCPAxis* valueAxis) : QCPBars(keyAxis, valueAxis), + m_textVisible(false), m_textAlignment(Qt::AlignCenter), m_spacing(5), m_font(QFont(QLatin1String("sans serif"), 12)) {} +void CustomBars::setTextVisible(bool visible) +{ + m_textVisible = visible; +} + void CustomBars::setTextAlignment(Qt::Alignment alignment) { m_textAlignment = alignment; @@ -67,27 +73,31 @@ void CustomBars::draw(QCPPainter* painter) ///---自定义逻辑-start--- //draw text - QRectF barRect = getBarRect(it->key, it->value); - painter->setFont(m_font); - QString text = QString::number(it->value, 'g', 2); //获取当前value值,保留两位精度 - QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip | m_textAlignment, text); //计算文字占用大小 - if(mKeyAxis.data()->orientation() == Qt::Horizontal) //水平轴为keyAxis + if(m_textVisible) { - if(mKeyAxis.data()->axisType() == QCPAxis::atTop) //上轴,文字放到柱图下方 - textRect.moveTopLeft(barRect.bottomLeft() + QPointF(0, m_spacing)); - else //下轴,文字放到柱图上方 - textRect.moveBottomLeft(barRect.topLeft() - QPointF(0, m_spacing)); - textRect.setWidth(barRect.width()); + QRectF barRect = getBarRect(it->key, it->value); + painter->setFont(m_font); + QString text = QString::number(it->value, 'g', 2); //获取当前value值,保留两位精度 + QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip | m_textAlignment, text); //计算文字占用大小 + if(mKeyAxis.data()->orientation() == Qt::Horizontal) //水平轴为keyAxis + { + if(mKeyAxis.data()->axisType() == QCPAxis::atTop) //上轴,文字放到柱图下方 + textRect.moveTopLeft(barRect.bottomLeft() + QPointF(0, m_spacing)); + else //下轴,文字放到柱图上方 + textRect.moveBottomLeft(barRect.topLeft() - QPointF(0, m_spacing)); + textRect.setWidth(barRect.width()); + } + else //垂直轴为keyAxis + { + if(mKeyAxis.data()->axisType() == QCPAxis::atLeft) //左轴,文字放到柱图右侧 + textRect.moveTopLeft(barRect.topRight() + QPointF(m_spacing, 0)); + else //右轴,文字放到柱图左侧 + textRect.moveTopRight(barRect.topLeft() - QPointF(m_spacing, 0)); + textRect.setHeight(barRect.height()); + } + painter->drawText(textRect, Qt::TextDontClip | m_textAlignment, text); } - else //垂直轴为keyAxis - { - if(mKeyAxis.data()->axisType() == QCPAxis::atLeft) //左轴,文字放到柱图右侧 - textRect.moveTopLeft(barRect.topRight() + QPointF(m_spacing, 0)); - else //右轴,文字放到柱图左侧 - textRect.moveTopRight(barRect.topLeft() - QPointF(m_spacing, 0)); - textRect.setWidth(barRect.height()); - } - painter->drawText(textRect, Qt::TextDontClip | m_textAlignment, text); + ///---自定义逻辑-end--- } } @@ -114,6 +124,8 @@ dpBarsChart::dpBarsChart(QWidget* parent) mainLayout->addWidget(m_pCustomPlot); setLayout(mainLayout); + m_updateData = false; + connect(DataManager::instance(), &DataManager::dataUpdated, this, &dpBarsChart::onSignal_dataUpdated); } @@ -185,13 +197,23 @@ void dpBarsChart::setTimeRange(TimeUnit unit) {} void dpBarsChart::setDateTime(const QDateTime& dateTime) -{} +{ + if(m_updateData) + { + for(auto it = m_bars.begin(); it != m_bars.end(); ++it) + DataManager::instance()->requestData(it.key(), this); + + m_pCustomPlot->replot(); + } +} void dpBarsChart::viewHistoricalData(const QDateTime& dateTime) {} void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) { + m_updateData = false; //停止更新数据 + //先清除现有图形(直方图不像曲线一样有连续的过程展现,所以不采用动态更新,每次都清除、重新创建) //m_pBarsGroup->clear(); m_pCustomPlot->clearPlottables(); @@ -237,6 +259,7 @@ void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) bars.dataType = dataType; bars.color = colorData.value(); CustomBars* qBars = new CustomBars(keyAxis, valueAxis); + qBars->setTextVisible(true); qBars->setName(bars.name); qBars->setPen(bars.color); //边框颜色 qBars->setBrush(bars.color); //填充颜色 @@ -261,6 +284,13 @@ void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) } m_bars.insert(dataID, bars); + + //实时模拟数据 + DataManager::instance()->registerDataSource(dataID, [](){ + static double min = 0, max = 10.0; + double randomFloat = min + QRandomGenerator::global()->generateDouble() * (max - min); + return QVariant::fromValue(randomFloat); + }); } if(groupByType) @@ -308,6 +338,8 @@ void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) keyAxis->setRange(0, ticks.count() + 1); valueAxis->setTickLabels(true); + QSharedPointer fixedTicker(new QCPAxisTickerFixed); + valueAxis->setTicker(fixedTicker); valueAxis->setRange(0, 11); for(auto it = m_bars.begin(); it != m_bars.end(); ++it) @@ -317,8 +349,8 @@ void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) //随机模拟值 QVector values; - double randomVaule = 1 + QRandomGenerator::global()->generateDouble() * (8 - 1); - values << randomVaule; + //double randomVaule = 1 + QRandomGenerator::global()->generateDouble() * (8 - 1); + values << 0; Bars bar = it.value(); bar.qBars->setData(bar.keys, values); @@ -337,8 +369,33 @@ void dpBarsChart::synchronizeConfigData(const configurationResults& cfg) else m_pCustomPlot->legend->setVisible(false); - m_pCustomPlot->replot(); + //m_pCustomPlot->replot(); + m_updateData = true; } -void dpBarsChart::onSignal_dataUpdated(const QString& dataKey, const QVariant& data, const QDateTime& timestamp) -{} +void dpBarsChart::onSignal_dataUpdated(const QString& dataID, const QVariant& data, const QDateTime& timestamp) +{ + auto it = m_bars.find(dataID); + if(it != m_bars.end()) + { + static double marginFactor = 1.0; + double dData = data.toDouble(); + Bars bar = it.value(); + //调整所在轴的范围 + QCPRange range = bar.qBars->valueAxis()->range(); + if(dData > range.upper) + { + double upper = dData + marginFactor; + bar.qBars->valueAxis()->setRangeUpper(upper); + } + else if(dData < range.lower) + { + double lower = dData - marginFactor; + bar.qBars->valueAxis()->setRangeLower(lower); + } + //更新值 + QVector values; + values << dData; + bar.qBars->setData(bar.keys, values); + } +} diff --git a/dataPanel/dpBarsChart.h b/dataPanel/dpBarsChart.h index defcd30..eec1451 100644 --- a/dataPanel/dpBarsChart.h +++ b/dataPanel/dpBarsChart.h @@ -24,6 +24,7 @@ public: double spacing() { return m_spacing; } QFont font() { return m_font; } + void setTextVisible(bool); void setTextAlignment(Qt::Alignment); void setSpacing(double); void setFont(QFont); @@ -32,6 +33,7 @@ protected: virtual void draw(QCPPainter* painter) override; private: + bool m_textVisible; Qt::Alignment m_textAlignment; //文字对齐方式 double m_spacing; //文字与柱状图之间的间距,单位为像素 QFont m_font; //文字的字体 @@ -52,7 +54,7 @@ public: void synchronizeConfigData(const configurationResults&) override; public slots: - void onSignal_dataUpdated(const QString& dataKey, const QVariant& data, const QDateTime& timestamp); + void onSignal_dataUpdated(const QString& dataID, const QVariant& data, const QDateTime& timestamp); private: struct Bars @@ -78,6 +80,7 @@ private: //QCPBarsGroup* m_pBarsGroup; QHash m_bars; QHash m_barsGroups; + bool m_updateData; }; #endif diff --git a/dataPanel/dpConfigurationDialog.cpp b/dataPanel/dpConfigurationDialog.cpp index 61e44b6..f32c0da 100644 --- a/dataPanel/dpConfigurationDialog.cpp +++ b/dataPanel/dpConfigurationDialog.cpp @@ -293,6 +293,7 @@ void dpConfigurationDialog::setPanel(DataPanel* pPanel) { ui->specialSettings->setVisible(true); ui->specialSettings->setCurrentIndex(1); + ui->barOrientation->setCurrentIndex((int)pPanel->m_cofigurationResults.barOrientataion); break; } default: @@ -363,7 +364,6 @@ void dpConfigurationDialog::onBtnClicked_confirm() m_pDataPanel->m_cofigurationResults.dataServiceIP = ui->serviceIP->text(); m_pDataPanel->m_cofigurationResults.dataServicePort = ui->servicePort->text().toInt(); m_pDataPanel->m_cofigurationResults.showLegend = ui->radioBtn_showLegend->isChecked(); - m_pDataPanel->m_cofigurationResults.groupByType = ui->radioBtn_groupByType->isChecked(); m_pDataPanel->m_cofigurationResults.axisArrangement = (AxisArrangementMode)ui->axisArrangement->currentIndex(); DataPanelType panelType = m_pDataPanel->getType(); @@ -380,6 +380,12 @@ void dpConfigurationDialog::onBtnClicked_confirm() } break; } + case barChart: + { + m_pDataPanel->m_cofigurationResults.barOrientataion = (BarOrientation)ui->barOrientation->currentIndex(); + m_pDataPanel->m_cofigurationResults.groupByType = ui->radioBtn_groupByType->isChecked(); + break; + } default: break; } diff --git a/dataPanel/dpGlobals.h b/dataPanel/dpGlobals.h index 22004e9..fa39712 100644 --- a/dataPanel/dpGlobals.h +++ b/dataPanel/dpGlobals.h @@ -30,8 +30,8 @@ enum AxisArrangementMode //坐标轴排列方式 enum BarOrientation //直方图方向 { - Horizontal = 0, - Vertical + Vertical = 0, + Horizontal }; #include diff --git a/dataPanel/dpLineChart.cpp b/dataPanel/dpLineChart.cpp index 6359a85..b2f1acc 100644 --- a/dataPanel/dpLineChart.cpp +++ b/dataPanel/dpLineChart.cpp @@ -12,7 +12,7 @@ dpLineChart::dpLineChart(QWidget* parent) m_timeRange = 60 * 1000; m_axisArrangementMode = AlternateSides; - m_showLegend = false; + //m_showLegend = false; m_updateData = false; QBoxLayout* mainLayout = new QBoxLayout(QBoxLayout::LeftToRight); @@ -81,7 +81,7 @@ void dpLineChart::initQCP() m_pCustomPlot->yAxis2->grid()->setPen(m_chartStyle.gridPen); //x轴用时间格式 QSharedPointer timeTicker(new QCPAxisTickerDateTime); - timeTicker->setDateTimeFormat("hh:mm:ss:zzz\nyyyy/MM/dd"); + timeTicker->setDateTimeFormat("hh:mm:ss"); //qDebug() << timeTicker->dateTimeFormat(); m_pCustomPlot->xAxis->setTicker(timeTicker); //qDebug() << m_pCustomPlot->xAxis->range(); @@ -163,62 +163,135 @@ void dpLineChart::reLayoutLegend() void dpLineChart::setTimeRange(TimeUnit unit) { + QSharedPointer ticker = m_pCustomPlot->xAxis->ticker(); + QSharedPointer dateTicker = qSharedPointerCast(ticker); + switch(unit) { case TU_Year: + { m_timeRange = m_curDateTime.date().daysInYear() * 24 * 60 * 60 * (qint64)1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("dd/MM\nyyyy"); break; + } case TU_Month: + { m_timeRange = m_curDateTime.date().daysInMonth() * 24 * 60 * 60 * (qint64)1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("dd/MM\nyyyy"); break; + } case TU_Day: + { m_timeRange = 24 * 60 * 60 * 1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("dd/MM\nyyyy"); break; + } case TU_Hour: + { m_timeRange = 60 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm"); break; + } case TU_Minute_30: + { m_timeRange = 30 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm"); break; + } case TU_Minute_20: + { m_timeRange = 20 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm"); break; + } case TU_Minute_15: + { m_timeRange = 15 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm"); break; + } case TU_Minute_10: + { m_timeRange = 10 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm"); break; + } case TU_Minute_5: + { m_timeRange = 5 * 60 *1000; break; + } case TU_Minute_3: + { m_timeRange = 3 * 60 *1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss"); break; + } case TU_Minute_1: + { m_timeRange = 60 * 1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss"); break; + } case TU_Second_30: + { m_timeRange = 30 * 1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss"); break; + } case TU_Second_10: + { m_timeRange = 10 * 1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss"); break; + } case TU_Second_1: + { m_timeRange = 1 * 1000; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss:zzz"); break; + } case TU_MSecond_500: + { m_timeRange = 500; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss:zzz"); break; + } case TU_MSecond_100: + { m_timeRange = 100; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss:zzz"); break; + } case TU_MSecond_50: + { m_timeRange = 50; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss:zzz"); break; + } case TU_MSecond_10: + { m_timeRange = 10; + if(!dateTicker.isNull()) + dateTicker->setDateTimeFormat("hh:mm:ss:zzz"); break; + } default: break; } @@ -459,6 +532,8 @@ void dpLineChart::synchronizeConfigData(const configurationResults& cfg) } graph.qGraph = newGraph; m_graphs.insert(graphID, graph); + + //实时模拟数据 DataManager::instance()->registerDataSource(graphID, [](){ static double min = 0, max = 10.0; double randomFloat = min + QRandomGenerator::global()->generateDouble() * (max - min); diff --git a/dataPanel/dpLineChart.h b/dataPanel/dpLineChart.h index d9f9abd..2cdf3be 100644 --- a/dataPanel/dpLineChart.h +++ b/dataPanel/dpLineChart.h @@ -70,7 +70,7 @@ private: QVector m_axes; QHash m_graphs; AxisArrangementMode m_axisArrangementMode; - bool m_showLegend; + //bool m_showLegend; bool m_updateData; }; diff --git a/source/dataManager.cpp b/source/dataManager.cpp index b0d6a4f..1a2b65d 100644 --- a/source/dataManager.cpp +++ b/source/dataManager.cpp @@ -91,7 +91,8 @@ void DataManager::registerDataSource(const QString& dataKey, std::function - 0 + 1 @@ -769,12 +769,12 @@ background-color:transparent; - 水平方向 + 垂直方向 - 垂直方向 + 水平方向