如何使用Qt实现实时数据动态绘制的折线图效果
作者:极客晨风
基于Qt的 QChartView
和定时器来动态绘制折线图。它通过动画的方式逐步将数据点添加到图表上,并动态更新坐标轴的范围,提供了一个可以实时更新数据的折线图应用。以下是对代码的详细介绍及其功能解析:
代码概述
该程序使用Qt的 QChartView
作为图表绘制的基础,结合 QLineSeries
或 QSplineSeries
来绘制折线或样条曲线。程序通过定时器 (QTimer
) 控制数据点的动态绘制,并在绘图过程中实时更新坐标轴的显示范围。
主要功能
- 动态创建系列:可以动态创建多个曲线系列(
QLineSeries
或QSplineSeries
),每个系列对应一条折线或样条曲线。 - 动态添加数据点:通过
addPointAnimated()
函数,可以为每个系列动态添加数据点,并通过动画效果逐步连接新数据点。 - 定时更新:使用
QTimer
每隔一段时间调用animateDrawing()
函数,逐步将新点连接到已有的曲线上。 - 自动调整坐标轴范围:在绘制过程中,如果新点超出了当前坐标轴范围,坐标轴会自动调整以适应新的数据点。
代码结构
1. DynamicChart
类构造函数
DynamicChart::DynamicChart(QWidget *parent) : QChartView(new QChart(), parent), m_chart(this->chart()) { m_chart->setTitle("Dynamic Data Plot"); m_chart->legend()->hide(); setRenderHint(QPainter::Antialiasing); // 设置图表主题和隐藏图例 m_chart->setTheme(QChart::ChartTheme::ChartThemeDark); // 创建共用的坐标轴 axisX = new QValueAxis(); axisX->setRange(0, 100); m_chart->addAxis(axisX, Qt::AlignBottom); axisY = new QValueAxis(); axisY->setRange(0, 100); m_chart->addAxis(axisY, Qt::AlignLeft); // 设置定时器 connect(&timer, &QTimer::timeout, this, &DynamicChart::animateDrawing); timer.setInterval(30); // 动画更新间隔为30毫秒 resize(500,500); }
该构造函数中设置了图表的主题、坐标轴、以及定时器,定时器的作用是每隔30毫秒触发 animateDrawing()
函数,用于动态绘制数据。
2. createSeries()
函数
void DynamicChart::createSeries(int seriesId, const QString &name) { #ifdef LINE QLineSeries *series = new QLineSeries(); #else QSplineSeries *series = new QSplineSeries(); #endif series->setName(name); m_chart->addSeries(series); // 使用共用的坐标轴 series->attachAxis(axisX); series->attachAxis(axisY); seriesMap.insert(seriesId, series); }
该函数负责创建新的系列(折线或样条曲线),并将其添加到图表中。 seriesId
用于标识不同的曲线,name
则用于显示系列的名称。系列将共享同一套坐标轴。
3. addPointAnimated()
函数
void DynamicChart::addPointAnimated(int seriesId, const QPointF &point) { if (!seriesMap.contains(seriesId)) return; #ifdef LINE QLineSeries *series = seriesMap[seriesId]; #else QSplineSeries *series =seriesMap[seriesId]; #endif if (!series->points().isEmpty()) { lastPoint = series->points().last(); } else { lastPoint = point; // 第一个点直接添加 series->append(point); } newPoint = point; currentSeriesId = seriesId; currentStep = 0; stepsCount = 10; // 分10步完成连线 timer.start(); }
该函数用于为指定的系列添加新点,并通过动画效果使新点逐步出现在图表上。它会计算新点与最后一个点之间的插值,并逐步绘制曲线。
4. animateDrawing()
函数
void DynamicChart::animateDrawing() { #ifdef LINE QLineSeries *series = seriesMap[currentSeriesId]; #else QSplineSeries *series =seriesMap[currentSeriesId]; #endif if (currentStep >= stepsCount) { timer.stop(); series->append(newPoint); return; } qreal x = lastPoint.x() + (newPoint.x() - lastPoint.x()) * currentStep / stepsCount; qreal y = lastPoint.y() + (newPoint.y() - lastPoint.y()) * currentStep / stepsCount; series->append(x, y); // 动态更新坐标轴 if (x > axisX->max()) { axisX->setMax(x + 10); } if (y > axisY->max() || y < axisY->min()) { axisY->setMax(qMax(y + 10, axisY->max())); axisY->setMin(qMin(y - 10, axisY->min())); } currentStep++; }
该函数实现了通过定时器触发的动态绘制。它逐步将新点与前一个点连接,并动态调整坐标轴的范围以适应新增数据。
主窗口逻辑
最后的代码片段展示了如何使用 DynamicChart
类创建一个包含多个曲线的图表,并通过按钮控制定时器的启动与停止:
setMinimumSize(QSize(800,500)); chartView = new DynamicChart(this); chartView->createSeries(1, "Test Series 1"); chartView->createSeries(2, "Test Series 2"); chartView->createSeries(3, "Test Series 3"); chartView->createSeries(4, "Test Series 4"); QTimer *timer = new QTimer; connect(timer, &QTimer::timeout, this, [=]() { int m_id = QRandomGenerator::global()->bounded(1, 5); chartView->addPointAnimated(m_id, QPointF(m_index++, QRandomGenerator::global()->bounded(100))); }); startButton = new QRadioButton("StartDrawing", this); connect(startButton, &QRadioButton::clicked, [=](bool arg) { if (arg) timer->start(100); else timer->stop(); });
通过 QRadioButton
控制定时器的启停,点击按钮后,程序将开始在图表上随机添加点,并动态绘制折线或样条曲线。
结论
此程序通过Qt的 QChartView
和定时器,实现了一个能够动态绘制多条曲线的折线图表。通过定时器控制数据点的逐步绘制,并结合坐标轴的动态更新,使得该图表在绘图过程中能够自动适应数据的变化。这种方式适用于需要实时显示数据变化的场景,如传感器数据的实时监控或动态性能分析等。
到此这篇关于使用Qt实现实时数据动态绘制的折线图示例的文章就介绍到这了,更多相关Qt动态折线图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!