牛骨文教育服务平台(让学习变的简单)
博文笔记

Qt Charts 动态实时折线图绘制

创建时间:2017-10-17 投稿人: 浏览次数:3896

在Qt Charts发布之前, Qt比较著名两个画图插件是 qwt和Qcustom, 其中Qcustom较轻量,只需要在project 中包含qcustomplot.h 和 qcustomplot.cpp 几乎就可以使用。

相比Qcustom,qwt功能更为强大,但是它的安装十分麻烦,阻挡了很多人(包括我)的使用。

但是qwt只是对静态图表的表示非常不错,动态曲线性能并不突出。如果只是静态绘图,或者动态绘制的点并不多,继续用qwt甚至Qcustom完全没问题。

但是如果是新入手Qt绘图,用Qt charts显然是更好的选择,因为它在各方面都比前两者要好,并且也易于使用。

并且qml也支持charts,qml的渲染默认用GPU,成长性更好。

如果你在安装Qt的时候,选择了Qt charts部分,那么在Qt中使用charts 只需要 在 .pro文件中

QT += charts

并且在程序的开头加上一句 using namespace Qtcharts或者一个宏 QT_CHARTS_USE_NAMESPACE 


进入主题: 动态实时折线图绘制

动态绘图,也就是说折线随着横坐标的增长而实时变化。

从这一秒和上一秒的变化看来,就是坐标轴不动,整个图像往前移了一个单位,然后在空出的最后一个位置增加了一个新的点。

想一下,只要你的显示器不能够随着横坐标的增长变宽,上面说的就是不得不做的事情。或者除非你不把最前面的那个点淘汰掉,但是那样的话,你的点只有增,没有删,随着时间的增长,点越来越多,曲线最后只会挤成一团,啥也看不清。

【多说一句,从相对的角度来说,既然可以把图像往前移一个单位,当然也可以坐标轴往后移一个单位,两者造成的结果当然是一样的。

Qt有一个函数scroll可以实现后者的功能,它有两个参数,可以设置每次x、y轴向右和向上滚动的距离。但是scroll函数绘制坐标轴感觉很奇怪……真的有一种在滚的感觉,看起来很难受,具体可以看Qt欢迎界面里面的一个示例子dynamicspline】

把整个图画往前移一个单位这个操作,这就是动态绘图的核心思想。

除了往前移一个单位这个操作,还要有一个触发这个操作的信号。

一般来说,当产生动态绘图这个需求时,都会有一个驱动X轴随时间变化而增长的因素。或者是传感器上读取到一个数据就画一个点,或者说其它控件传过来一个数据就画一个点等等。

如果仅仅是为了学习,也可以声明一个时间戳对象,当规定的时间戳被触发一次,就画一个点。

显然,传感器,其它控件,时间戳都是信号,画图函数是槽。信号被触发一次,槽函数就画一个点。

事先声明,我没用过时间戳,我做的项目是手机蓝牙传过来一个RSSI值就画一个点,之后我贴的代码也是这样写的。

了解了以上两点,动态绘图也就没什么难的了,但是具体还是要看绘图的软件提供什么接口来操作。 

下面具体说说Qt charts 怎么操作。

Qt charts中,可以主要一下几个类: QChart 和 QChartView,QChart是用什么画,差不多画笔的意思,QChartView是在什么上画,差不多画布的意思。

[cpp] view plain copy
  1. QChartView *chartView = new QChartView(this);    
  2. chartView *chart = chartView->chart();

就新建了一个QChartView 和一个 QChart 指针。

 类 Series 是用来添加数据的对象(可以理解为一个集合)。常见的 QLineSeries,折线类,画出来的先棱角更强,QSplineSeries,曲线类,画出来更平滑,QScatterSeries,点类,画出来是一个个单独的点。Qt文档对这些类都有很详细的说明,并配有图画。

类似于QChart 、QChartView、Series ,还有QValueAxis类(数值类型的坐标轴)等等,不再啰嗦,下面的代码里都有。并且有很详细的注释,想学的朋友一定仔细看一遍肯定能看明白。

[cpp] view plain copy
  1. //新建 一个QLineSeries对象 指针  
  2. QLineSeries* series = new QLineSeries();  
  3. // 添加数据  
  4. series->append(0, 6);   
  5. series->append(2, 4);  
  6.  ...    
  7. //把series 这条线画出来  
  8. chart->addSeries(series);

主要就是两个文件mainwindow.h和mainwindow.cpp,我删掉了一些和绘图没关系的变量,程序是不可以运行的,但是绘图的东西都在里面,可以参考。

[cpp] view plain copy
  1. #ifndef MAINWINDOW_H  
  2. #define MAINWINDOW_H  
  3.   
  4. #include <QMainWindow>  
  5. #include <QChartView>  
  6. #include <QLineSeries>  
  7. #include <QScatterSeries>  
  8. #include <QValueAxis>  
  9.   
  10. QT_CHARTS_USE_NAMESPACE  
  11.   
  12. namespace Ui {  
  13. class MainWindow;  
  14. }  
  15.   
  16. class MainWindow : public QMainWindow  
  17. {  
  18.     Q_OBJECT  
  19.   
  20. public:  
  21.     explicit MainWindow(QWidget *parent = 0);  
  22.     ~MainWindow();  
  23.   
  24. public slots:  
  25.      void onIBScanTick(QList<IBResult*> list);  
  26. private:  
  27.     Ui::MainWindow *ui;  
  28.     int t = 0;  
  29.     int maxy = -1000,miny = 1000;  
  30.     QString major_minor ;  
  31.     QSet<QString> ib_set;  
  32.   
  33.     QLineSeries *series0;  
  34.     QLineSeries *series1;  
  35.   
  36.   
  37.     QScatterSeries * scatseries0;  
  38.     QScatterSeries * scatseries1;  
  39.   
  40.     QChart *chart;  
  41.     QChartView *chartView;  
  42.   
  43.     QValueAxis *axisX2;  
  44.     QValueAxis *axisY2;  
  45.     QValueAxis *axisX;  
  46.     QValueAxis *axisY;  
  47. };  
  48. #endif // MAINWINDO0W_H</span>  

[cpp] view plain copy
  1. #include "mainwindow.h"  
  2. #include "ui_mainwindow.h"  
  3. #include "kalmanfilter.h"  
  4. #include <QDebug>  
  5. #include <QVector>  
  6. #include "ibscanner/ibscanner.h"  
  7. #include "kalmanfilter_now.h"  
  8. #include "global_data.h"  
  9. #include <QInputDialog>  
  10.   
  11. MainWindow::MainWindow(QWidget *parent) :  
  12.     QMainWindow(parent),  
  13.     ui(new Ui::MainWindow)  
  14. {  
  15.     ui->setupUi(this);  
  16.     global_widget* glw = global_widget::inst();  
  17.     major_minor = glw->str;  
  18.   
  19.      //设置一些QPen,以便待会设置线条的颜色,宽度  
  20.     QPen p0 ,p1,p2;  
  21.     p0.setWidth(3);  
  22.     p0.setColor(Qt::blue);  
  23.   
  24.     p1.setWidth(3);  
  25.     p1.setColor(Qt::red);  
  26.     p1.setBrush(Qt::red);  
  27.   
  28.     p2.setWidth(3);  
  29.     p2.setColor(Qt::black);  
  30.     p2.setBrush(Qt::black);  
  31.   
  32.     //QScatterSeries类的点,为了突出每个点的位置,Qcharts画的出的线每个点的痕迹几乎看不到  
  33.     scatseries0 = new QScatterSeries(this);  
  34.     scatseries0->setMarkerShape(QScatterSeries::MarkerShapeCircle);//设置点的类型  
  35.     scatseries0->setMarkerSize(10); //设置点的大小  
  36.   
  37.     scatseries1 = new QScatterSeries(this);  
  38.     scatseries1->setMarkerShape(QScatterSeries::MarkerShapeCircle);  
  39.     scatseries1->setMarkerSize(10);  
  40.     scatseries1->setPen(p1);  
  41.   
  42.     scatseries2 = new QScatterSeries(this);  
  43.     scatseries2->setMarkerShape(QScatterSeries::MarkerShapeCircle);  
  44.     scatseries2->setMarkerSize(10);  
  45.     scatseries2->setPen(p2);  
  46.   
  47.     series0 = new QLineSeries(this);  //线条0  
  48.     series0->setPen(p0);  
  49.   
  50.     series1 = new QLineSeries(this);  //线条1  
  51.     series1->setPen(p1);  
  52.   
  53.     series2 = new QLineSeries(this);  
  54.     series2->setPen(p2);  
  55.   
  56.    /********************************/  
  57.   
  58.     /*设置画笔和画布*/  
  59.     chartView = new QChartView(this);  
  60.     chart = chartView->chart();  
  61.   
  62.     chart->legend()->hide(); //隐藏图例  
  63.     chartView->setRenderHint(QPainter::Antialiasing); //设置抗锯齿  
  64.     chartView->resize(1200, 600);   //画布大小  
  65.     chartView->show(); //显示  
  66.   
  67.     /*添加数据*/  
  68.     chart->addSeries(scatseries0);  //把各个线条添加到chart中  
  69.     chart->addSeries(scatseries1);  
  70.     chart->addSeries(scatseries2);  
  71.     chart->addSeries(series0);  
  72.     chart->addSeries(series1);  
  73.     chart->addSeries(series2);  
  74.   
  75.     /*设置第一坐标轴*/   // rssi - dis  
  76.   
  77.     axisX = new QValueAxis;  
  78.     axisX->setRange(0,5);   //设置X坐标范围  
  79.     axisX->setTitleText("t/s"); //设置X坐标名字  
  80.   
  81.     axisY = new QValueAxis;  
  82.     axisY->setRange(0,50);  
  83.     axisY->setTitleText("dis/m");  
  84.   
  85.     //别忘记把坐标轴添加到chart  
  86.     chart->addAxis(axisX, Qt::AlignTop);  //并且XY轴的位置是上和右  
  87.     chart->addAxis(axisY, Qt::AlignRight);  
  88.   
  89.     /* 添加第二坐标轴*/   //t - dis  
  90.     axisX2 = new QValueAxis;  
  91.     axisX2->setLabelFormat("%g");  
  92.     axisX2->setMinorTickCount(15);  
  93.     axisX2->setTitleText("t/s");  
  94.     axisX2->setRange(0,5);  
  95.   
  96.     axisY2 = new QValueAxis;  
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。