[QT QCustomPlot]实时折线图(坐标轴可缩放)
1.QCustomPlot介绍
QCustomPlot 是一个用于 Qt 框架的高性能、可扩展的图表库,专门设计用于显示和交互复杂的绘图。它提供了一个非常灵活的接口,允许开发者在 Qt 应用程序中轻松地实现各种图表和图形。以下是 QCustomPlot 的一些关键特性和用途:
-
图表类型:QCustomPlot 支持多种图表类型,包括折线图、散点图、柱状图、饼图、面积图等。
-
实时更新:QCustomPlot 特别适合于需要实时更新数据的场景,例如股票价格监控、传感器数据可视化等。
-
交互性:用户可以与图表进行交互,例如缩放、平移、点击图表元素等。
-
自定义:QCustomPlot 提供了高度的自定义能力,包括轴、图例、工具提示等,以及图表的样式和颜色。
-
性能:由于其优化的绘图算法,QCustomPlot 能够处理大量的数据点而不会显著降低性能。
-
事件处理:QCustomPlot 支持事件处理,例如点击、悬停等,这使得开发者可以为图表元素添加自定义的行为。
-
导出功能:QCustomPlot 允许将图表导出为图像文件,如 PNG 或 SVG 格式。
-
集成:QCustomPlot 可以轻松集成到任何基于 Qt 的应用程序中,无论是桌面应用还是移动应用。
-
文档和示例:QCustomPlot 提供了详细的文档和示例代码,帮助开发者快速上手。
-
开源:QCustomPlot 是开源的,可以在遵守其许可证的条件下免费使用和修改。
在实际应用中,QCustomPlot 可以用于科学计算、数据分析、商业报告、实时监控系统等多种场合,它的灵活性和性能使其成为 Qt 开发者在需要图表功能时的一个受欢迎的选择。
2.QCustomPlot下载
官网:https://www.qcustomplot.com/
下载解压,解压后文件:
其中qcustomplot.cpp及qcustomplot.h是移植需要用到的文件
3.移植
我这里以qt5.12.5举例,其他版本操作一致;
①新建Mainwindow项目
②添加相关文件
将qcustomplot.cpp及qcustomplot.h添加进工程路径
在xxxx.pro文件中添加如下内容:
添加完成后可以先构建一下看看有没有报错;
③ui文件添加qcustomplot控件
qcustomplot控件是基于qwidget控件的;我们先拖一个qwidget控件进来,并调整合适大小;
鼠标右键刚拖进来的qwidget,选择“提升为…”
这样,qwidget类就会被提升为qcustomplot类;
将objectName改为:customPlot
4.用户程序
①mainwindow.h
#include <QTimer> //设置定时器
#include <QDateTime> //获取时间
②mainwindow.cpp
新建两个变量用于图表数据显示:
float Speed_CatTom;
float Speed_MouseJerry;
编写QCustomPlot图表初始化代码:
/**
* @brief QCustomPlot控件初始化
* @param void
* @return void
*/
void MainWindow::QCustomPlotInit()
{
QCustomPlot* customPlot = ui->customPlot;
/* 性能优化? */
ui->customPlot->replot();
//曲线1
customPlot->addGraph();
QPen tar;
tar.setColor(QColor(40, 110, 255)); //曲线1蓝色
tar.setStyle(Qt::PenStyle::DashLine); //虚线
tar.setWidth(3); //线宽
customPlot->graph(0)->setPen(tar);
//曲线2
customPlot->addGraph();
QPen rec;
rec.setColor(QColor(255, 110, 40)); //曲线1蓝色
rec.setWidth(3); //线宽
customPlot->graph(1)->setPen(rec);
//customPlot->graph(1)->setPen(QPen(QColor(255, 110, 40)));//曲线2红色
//设置标题
// customPlot->plotLayout()->insertRow(0);
// customPlot->plotLayout()->addElement(0, 0, new QCPTextElement(customPlot, "目标与实时转速", QFont("sans", 12, QFont::Bold)));
// //设置渐变颜色:0-1之间;
// QLinearGradient gradient(0, 0, 0, 400);
// gradient.setColorAt(0, QColor(90, 90, 90));
// gradient.setColorAt(0.38, QColor(105, 105, 105));
// gradient.setColorAt(1, QColor(70, 70, 70));
// customPlot->setBackground(QBrush(gradient));
//坐标轴使用时间刻度
QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
timeTicker->setTimeFormat("%h:%m:%s");
customPlot->xAxis->setTicker(timeTicker);
//四边安上坐标轴
customPlot->axisRect()->setupFullAxesBox();
//设置y轴范围
customPlot->yAxis->setRange(0 ,3500);
//设置x、y轴标签
customPlot->xAxis->setLabel("时间");
customPlot->yAxis->setLabel("奔跑速度");
//设置x、y轴标签颜色
// customPlot->xAxis->setBasePen(QPen(Qt::white));
// customPlot->xAxis->setTickPen(QPen(Qt::white));
// customPlot->xAxis->setSubTickPen(QPen(Qt::white));
// customPlot->xAxis->setTickLabelColor(Qt::white);
// customPlot->xAxis->setLabelColor(Qt::white);
// customPlot->yAxis->setBasePen(QPen(Qt::white));
// customPlot->yAxis->setTickPen(QPen(Qt::white));
// customPlot->yAxis->setSubTickPen(QPen(Qt::white));
// customPlot->yAxis->setTickLabelColor(Qt::white);
// customPlot->yAxis->setLabelColor(Qt::white);
//设置图例边框
customPlot->legend->setBorderPen(Qt::NoPen);
//图例字体及大小
QFont legendFont = font();
legendFont.setPointSize(10);
customPlot->legend->setFont(legendFont);
//显示图例
customPlot->legend->setVisible(true);
//设置图例背景色
customPlot->legend->setBrush(QColor(255, 255, 255, 100));
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignLeft|Qt::AlignTop); // make legend align in top left corner or axis rect
//图例说明-与上述添加曲线颜色对应
customPlot->graph(0)->setName("Tom速度");
customPlot->graph(1)->setName("Jerry速度");
// 设置 y轴为线性刻度
customPlot->yAxis->setScaleType(QCPAxis::stLinear); //设置线性刻度
customPlot->yAxis2->setScaleType(QCPAxis::stLinear);
// 设置坐标轴范围
// customPlot->xAxis->setRange(0, 19.9);
customPlot->yAxis->setRange(0, 40);
customPlot->yAxis->setRangeLower(0);
// //设置图表自动缩放
// ui->customPlot->rescaleAxes();
// 使坐标轴范围可拖动和缩放
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
// 设置右上角坐标轴与左下角坐标轴一致
customPlot->axisRect()->setupFullAxesBox();
// 使上下轴、左右轴范围同步
connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
//定时器连接槽函数realtimeDataSlot
connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
dataTimer.start(0); // 间隔时间 0ms表示尽可能快的触发
}
编写图表添加数据函数
/**
* @brief 添加数据
* @param void
* @return void
*/
void MainWindow::realtimeDataSlot()
{
QCustomPlot* customPlot = ui->customPlot;
static QTime time(QTime::currentTime());
double key = time.elapsed()/1000.0; // 开始到现在的时间,单位秒
static double lastPointKey = 0;
if (key-lastPointKey > 0.001) // 快速添加数据
{
// 添加数据到graph
customPlot->graph(1)->addData(key, Speed_CatTom);
customPlot->graph(0)->addData(key, Speed_MouseJerry);
//记录当前时刻
lastPointKey = key;
}
// 曲线能动起来的关键在这里,设定x轴范围为最近8个时刻
customPlot->xAxis->setRange(key, 8, Qt::AlignRight);
//绘图
customPlot->replot();
}
模拟数据更新
//创建一个200ms的定时器模拟数据更新
connect(&GetSpeedTimer, SIGNAL(timeout()), this, SLOT(GetTomAndJerrySpeed()));
GetSpeedTimer.start(200); //200ms
//数据更新函数
void MainWindow::GetTomAndJerrySpeed()
{
qDebug("data update...");
Speed_CatTom = QRandomGenerator::global()->bounded(0,30);//产生随机数(0-30)
Speed_MouseJerry = QRandomGenerator::global()->bounded(0,30);//产生随机数(0-30)
}
5.效果展示
调整模拟数据更新时间,10ms1次,效果如下: