Qt使用QCustomPlot绘制动态曲线。
曲线动态更新,主要分为两种情况:整组刷新的定长曲线,动态增长的不定长曲线。
而整组刷新的不定长曲线比较特殊,适用环境较少,在此不做讲述。主要对上述两种情况的应用进行讲解。
整组刷新的定长曲线 适用于显示当前内容,并不需要对历史数据进行记录的情况。实现较为简单。
动态增长的不定长曲线 多显示为波形图,由于记录着历史数据,所以广泛使用在科研、学术、物联等实时绘图领域。
区分这俩的方法,可以观察更新曲线数据点是如何在代码中实现:如果使用 setData ,多半是 整组刷新的定长曲线;而使用 addData,大多为 动态增长的不定长曲线。
工程源码已同步至GitHub,欢迎下载学习。使用时记得遵循GPLv3哦。
我的学习例程仓库,GitHub:QCustomPlot 学习例程下载
动态增长的不定长曲线 - 波形图
由于波形图的应用范围较广,以此为例程。
绘制动态曲线包括两个部分:曲线动态更新,坐标轴动态更新。
例程中,坐标轴的动态更新方式:如果x坐标点小于1000,则显示0~当前;大于1000,显示(当前-1000)~ 当前。
更新绘图,replot,在高填充下太浪费资源。有另一种方式replot(QCustomPlot::rpQueuedReplot),可避免重复绘图。
!更新绘图的最好的方法还是将数据填充、和更新绘图分隔开。将更新绘图单独用定时器更新。例程中数据量较少,没用定时器单独更新,实际工程中建议大家加上。
帧率显示的代码参考这篇文章,感谢:https://blog.csdn.net/yxy244/article/details/100099876
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 给widget绘图控件,设置个别名,方便书写
pPlot1 = ui->widget_1;
// 状态栏指针
sBar = statusBar();
// 初始化图表1
QPlot_init(pPlot1);
}
MainWindow::~MainWindow()
{
delete ui;
}
// 绘图图表初始化
void MainWindow::QPlot_init(QCustomPlot *customPlot)
{
// 创建定时器,用于定时生成曲线坐标点数据
QTimer *timer = new QTimer(this);
timer->start(10);
connect(timer,SIGNAL(timeout()),this,SLOT(TimeData_Update()));
// 图表添加两条曲线
pGraph1_1 = customPlot->addGraph();
pGraph1_2 = customPlot->addGraph();
// 设置曲线颜色
pGraph1_1->setPen(QPen(Qt::red));
pGraph1_2->setPen(QPen(Qt::black));
// 设置坐标轴名称
customPlot->xAxis->setLabel("X");
customPlot->yAxis->setLabel("Y");
// 设置y坐标轴显示范围
customPlot->yAxis->setRange(120,-120);
// 显示图表的图例
customPlot->legend->setVisible(true);
// 添加曲线名称
pGraph1_1->setName("波形1");
pGraph1_2->setName("波形2");
// 设置波形曲线的复选框字体颜色
ui->checkBox_1->setStyleSheet("QCheckBox{color:rgb(255,0,0)}");//设定前景颜色,就是字体颜色
// 允许用户用鼠标拖动轴范围,用鼠标滚轮缩放,点击选择图形:
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
}
// 定时器溢出处理槽函数。用来生成曲线的坐标数据。
void MainWindow::TimeData_Update(void)
{
// 生成坐标数据
static float f;
f += 0.01;
//qDebug() << sin(f)*100;
// 将坐标数据,传递给曲线
Show_Plot(pPlot1, sin(f)*100);
}
// 曲线更新绘图
void MainWindow::Show_Plot(QCustomPlot *customPlot, double num)
{
static double cnt;
cnt++;
// 给曲线添加数据
pGraph1_1->addData(cnt, num);
pGraph1_2->addData(cnt, num*-1);
// 设置x坐标轴显示范围,使其自适应缩放x轴,x轴最大显示1000个点
customPlot->xAxis->setRange((pGraph1_1->dataCount()>1000)?(pGraph1_1->dataCount()-1000):0, pGraph1_1->dataCount());
// 更新绘图,这种方式在高填充下太浪费资源。有另一种方式rpQueuedReplot,可避免重复绘图。
// 最好的方法还是将数据填充、和更新绘图分隔开。将更新绘图单独用定时器更新。例程数据量较少没用单独定时器更新,实际工程中建议大家加上。
//customPlot->replot();
customPlot->replot(QCustomPlot::rpQueuedReplot);
static QTime time(QTime::currentTime());
double key = time.elapsed()/1000.0; // 开始到现在的时间,单位秒
计算帧数
static double lastFpsKey;
static int frameCount;
++frameCount;
if (key-lastFpsKey > 1) // 每1秒求一次平均值
{
//状态栏显示帧数和数据总数
ui->statusbar->showMessage(
QString("%1 FPS, Total Data points: %2")
.arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
.arg(customPlot->graph(0)->data()->size()+customPlot->graph(1)->data()->size())
, 0);
lastFpsKey = key;
frameCount = 0;
}
}
隐藏曲线 graph
隐藏曲线 有两种方法:
1. setPen 设置为透明色的方法。但也会影响图例中的颜色。不建议使用。
2. setVisible 设置可见性属性。不会对图例有任何影响。推荐使用。
/// 隐藏曲线有两种方法:1.设置为透明色,但也会影响图例中的颜色 2.设置可见性属性
// 1.设置为透明色的方法,隐藏曲线,但也会影响图例中的颜色。不建议使用。
void MainWindow::on_checkBox_1_stateChanged(int arg1)
{
if(arg1){
// 显示
pGraph1_1->setPen(QPen(Qt::red));
}else{
// 不显示,透明色
pGraph1_1->setPen(QColor(0,0,0,0));
}
pPlot1->replot();
}
// 2.设置可见性属性,隐藏曲线,不会对图例有任何影响。推荐使用。
void MainWindow::on_checkBox_2_stateChanged(int arg1)
{
if(arg1){
pGraph1_2->setVisible(true);
}else{
pGraph1_2->setVisible(false);//void QCPLayerable::setVisible(bool on)
}
pPlot1->replot();
}
鼠标移动拖动、滚轮缩放、点击选中
因为在更新曲线的代码段中,增加了设置x轴范围,所以在此例程中左键拖动只适用于y轴。
以鼠标为中心滚轮缩放,和点击选中曲线 全部支持。手册搜索 iSelectPlottables,可以查找到更多功能。
QCustomPlot 自带 鼠标移动拖动、滚轮缩放、点击选中 等功能,只需要添加一段代码。
// 允许用户用鼠标拖动轴范围,以鼠标为中心滚轮缩放,点击选择图形:
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
// 设置鼠标滚轮的缩放倍率,如果不设置默认为0.85,大于1反方向缩放
//customPlot->axisRect()->setRangeZoomFactor(0.5);
// 设置鼠标滚轮缩放的轴方向,仅设置垂直轴。垂直轴和水平轴全选使用:Qt::Vertical | Qt::Horizontal
customPlot->axisRect()->setRangeZoom(Qt::Vertical);
发现个宝藏专栏,功能蛮实用的,感谢:https://blog.csdn.net/qq_31073871/article/details/90260275
更多 QCustomPlot控件的使用操作,会在本专栏的后续篇章介绍,一起学习进步。
工程源码已同步至GitHub,欢迎下载学习。使用时记得遵循GPLv3哦。
我的学习例程仓库,GitHub:QCustomPlot 学习例程下载