QT Charts 实时曲线绘画 实现不卡闪 丝滑变化!——学习笔记
前言:
我正在做MCU+FreeRtos下位机与Linux环境下QT上位机的模拟温湿度发送接收传输+数据曲线实时显示+LED灯控制系统,其中Qt Chart相关类曲线绘制也是第一次学习,通过网上检索+ai学习,笔记中代码都是源项目的代码为例,以此整理一篇学习笔记,帮助有和我一样想学习这些或有困扰的人。
除了这篇,对于我做好的这个简单的项目我也会发一篇文章详细记录下。
QT Chart 相关类介绍以及基础使用流程
QChart
这个类用来存放要绘制的曲线、坐标轴等等对象,你可以理解为一个存放的容器。
//创建图表容器
m_chart = new QChart();
m_chart->setTitle("温湿度实时曲线");
m_chart->setAnimationOptions(QChart::SeriesAnimations); // 仅曲线有动画
m_chart->setAnimationDuration(250); // 调整动画时长
QLineSeries
显示线条数据,例如折线、曲线等等,可以通过QChart的addSeries()函数来添加,
setName();setColor(Qt::red);可以分别用来设置线条的名字,颜色(红色为例)
//温度曲线
m_tempSeries = new QLineSeries();
m_tempSeries->setName("温度 (°C)");
m_tempSeries->setColor(Qt::red);
//湿度曲线
m_humiSeries = new QLineSeries();
m_humiSeries->setName("湿度 (%)");
m_humiSeries->setColor(Qt::blue);
//chart添加函数
m_chart->addSeries(m_tempSeries);
m_chart->addSeries(m_humiSeries);
QValueAxis
这是用来创建坐标轴的类。具体用法:
//创建x轴
m_axisX = new QValueAxis();
m_axisX->setTitleText("数据点");
m_axisX->setRange(0,MAX_DATA_POINTS);//设置x轴范围 0-50
m_axisX->setTickCount(6); // 固定显示6个刻度
//创建y轴
m_axisY = new QValueAxis();
m_axisY->setTitleText("数值");
m_axisY->setRange(0,100); //设置y轴范围 0-100
m_axisY->setTickCount(6);// 固定显示6个刻度
//将坐标轴添加到图表 方位分别是下和左
m_chart->addAxis(m_axisX, Qt::AlignBottom);
m_chart->addAxis(m_axisY, Qt::AlignLeft);
//关联曲线到坐标轴
m_tempSeries->attachAxis(m_axisX);
m_tempSeries->attachAxis(m_axisY);
m_humiSeries->attachAxis(m_axisX);
m_humiSeries->attachAxis(m_axisY);
//这里注意 要先将坐标轴添加到图表,然后再关联曲线到坐标轴。顺序反会报错
QChartView
表格视图类,用来存放QChart这个类,但是它还要搭配组件中QGraphicsView类控件,很像套娃(QChart->QChartView->QGraphicsView),其中QGraphicsView类控件要在ui中提升为QChartView类,这样就可以使用setChart()来显示了。


这样就可以了,我学习别人的文章的时候他们都说要加上
QT_CHARTS_USE_NAMESPACE,或者:using namespace QtCharts;但是可能是QT版本不一样,我的是6.8.3,如果加上后会报错说命令空间错误,删掉以后反而可以正常编译运行。当然QT += charts是一定要的。然后就可以添加视图显示了
//添加到视图
ui->Chart_View->setChart(m_chart); // 将图表对象设置到QgraphicsView控件上进行显示
ui->Chart_View->setRenderHint(QPainter::Antialiasing); // 抗锯齿,使曲线更平滑
最终效果

运行曲线以及曲线平滑移动

前面0-50还运行的好好的,可是当我运行到50之后,出现了曲线频繁闪动,很不丝滑难受。

曲线很“卡”,看上去,后面思考的时候想,每一次闪动是不是它代表曲线是被重新写入的,并不是一直在添加,而是一直在被重写,我查看代码,原来是在计数大于50之后的逻辑中,我添加了remove(0)这一实现,导致曲线对象在底层逻辑上是进行了删除重写操作,因为会出现“卡”的现象。
append(a,b);函数就是添加数据操作,a参数为第几个数,b为要插入的数据。
其中被注释的代码就是“罪魁祸首”
//更新曲线
m_tempSeries->append(m_dataCount,Temp_Data);
m_humiSeries->append(m_dataCount,Humi_Data);
m_dataCount++; //数据计数+1
//限制x轴显示范围
if (m_tempSeries->count() > MAX_DATA_POINTS) {
/*
//去除最旧的一个点
// 先判断是否有数据可删,避免越界崩溃
if (m_tempSeries->count() > 0) {
m_tempSeries->remove(0);
}
if (m_humiSeries->count() > 0) {
m_humiSeries->remove(0);
}
*/
// 更新X轴范围(保持显示最新的MAX_DATA_POINTS个点)
m_axisX->setRange(m_dataCount - MAX_DATA_POINTS, m_dataCount);
MAX_DATA_POINTS 为 50 (逻辑实现的是:每次往右一个单位,1-51 -> 2-52)
因此只需要利用setRange()函数更新x轴的范围,就可以实现丝滑平移动态曲线,

补充
例外,如果是这样不去remove(0)它,其实这个对象如果真的在实际中使用很长时间,那会计数到非常大的值,因此优化它的占用空间还是一个值得做的事情,比如可以用QTimer定时器固定时间去清除一定范围的值。再还有对于曲线的平滑优化,让他看起来更丝滑~。
更多推荐


所有评论(0)