在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. #include <QMainWindow>
  4. #include <QChartView>
  5. #include <QLineSeries>
  6. #include <QScatterSeries>
  7. #include <QValueAxis>
  8. QT_CHARTS_USE_NAMESPACE
  9. namespace Ui {
  10. class MainWindow;
  11. }
  12. class MainWindow : public QMainWindow
  13. {
  14. Q_OBJECT
  15. public:
  16. explicit MainWindow(QWidget *parent = 0);
  17. ~MainWindow();
  18. public slots:
  19. void onIBScanTick(QList<IBResult*> list);
  20. private:
  21. Ui::MainWindow *ui;
  22. int t = 0;
  23. int maxy = -1000,miny = 1000;
  24. QString major_minor ;
  25. QSet<QString> ib_set;
  26. QLineSeries *series0;
  27. QLineSeries *series1;
  28. QScatterSeries * scatseries0;
  29. QScatterSeries * scatseries1;
  30. QChart *chart;
  31. QChartView *chartView;
  32. QValueAxis *axisX2;
  33. QValueAxis *axisY2;
  34. QValueAxis *axisX;
  35. QValueAxis *axisY;
  36. };
  37. #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. MainWindow::MainWindow(QWidget *parent) :
  11. QMainWindow(parent),
  12. ui(new Ui::MainWindow)
  13. {
  14. ui->setupUi(this);
  15. global_widget* glw = global_widget::inst();
  16. major_minor = glw->str;
  17. //设置一些QPen,以便待会设置线条的颜色,宽度
  18. QPen p0 ,p1,p2;
  19. p0.setWidth(3);
  20. p0.setColor(Qt::blue);
  21. p1.setWidth(3);
  22. p1.setColor(Qt::red);
  23. p1.setBrush(Qt::red);
  24. p2.setWidth(3);
  25. p2.setColor(Qt::black);
  26. p2.setBrush(Qt::black);
  27. //QScatterSeries类的点,为了突出每个点的位置,Qcharts画的出的线每个点的痕迹几乎看不到
  28. scatseries0 = new QScatterSeries(this);
  29. scatseries0->setMarkerShape(QScatterSeries::MarkerShapeCircle);//设置点的类型
  30. scatseries0->setMarkerSize(10); //设置点的大小
  31. scatseries1 = new QScatterSeries(this);
  32. scatseries1->setMarkerShape(QScatterSeries::MarkerShapeCircle);
  33. scatseries1->setMarkerSize(10);
  34. scatseries1->setPen(p1);
  35. scatseries2 = new QScatterSeries(this);
  36. scatseries2->setMarkerShape(QScatterSeries::MarkerShapeCircle);
  37. scatseries2->setMarkerSize(10);
  38. scatseries2->setPen(p2);
  39. series0 = new QLineSeries(this);  //线条0
  40. series0->setPen(p0);
  41. series1 = new QLineSeries(this);  //线条1
  42. series1->setPen(p1);
  43. series2 = new QLineSeries(this);
  44. series2->setPen(p2);
  45. /********************************/
  46. /*设置画笔和画布*/
  47. chartView = new QChartView(this);
  48. chart = chartView->chart();
  49. chart->legend()->hide(); //隐藏图例
  50. chartView->setRenderHint(QPainter::Antialiasing); //设置抗锯齿
  51. chartView->resize(1200, 600);   //画布大小
  52. chartView->show(); //显示
  53. /*添加数据*/
  54. chart->addSeries(scatseries0);  //把各个线条添加到chart中
  55. chart->addSeries(scatseries1);
  56. chart->addSeries(scatseries2);
  57. chart->addSeries(series0);
  58. chart->addSeries(series1);
  59. chart->addSeries(series2);
  60. /*设置第一坐标轴*/   // rssi - dis
  61. axisX = new QValueAxis;
  62. axisX->setRange(0,5);   //设置X坐标范围
  63. axisX->setTitleText("t/s"); //设置X坐标名字
  64. axisY = new QValueAxis;
  65. axisY->setRange(0,50);
  66. axisY->setTitleText("dis/m");
  67. //别忘记把坐标轴添加到chart
  68. chart->addAxis(axisX, Qt::AlignTop);  //并且XY轴的位置是上和右
  69. chart->addAxis(axisY, Qt::AlignRight);
  70. /* 添加第二坐标轴*/   //t - dis
  71. axisX2 = new QValueAxis;
  72. axisX2->setLabelFormat("%g");
  73. axisX2->setMinorTickCount(15);
  74. axisX2->setTitleText("t/s");
  75. axisX2->setRange(0,5);
  76. axisY2 = new QValueAxis;
  77. axisY2->setRange(-100,-40);
  78. axisY2->setMinorTickCount(10);
  79. axisY2->setTitleText("dis/m");
  80. chart->addAxis(axisX2, Qt::AlignBottom); //并且XY轴的位置是下和左
  81. chart->addAxis(axisY2, Qt::AlignLeft);
  82. //还要指定这条线是对应的是哪个坐标轴
  83. scatseries0->attachAxis(axisX2);
  84. scatseries0->attachAxis(axisY2);
  85. scatseries1->attachAxis(axisX);
  86. scatseries1->attachAxis(axisY);
  87. scatseries2->attachAxis(axisX2);
  88. scatseries2->attachAxis(axisY2);
  89. series0->attachAxis(axisX2);
  90. series0->attachAxis(axisY2);
  91. series1->attachAxis(axisX);
  92. series1->attachAxis(axisY);
  93. series2->attachAxis(axisX2);
  94. series2->attachAxis(axisY2);
  95. IBScanner* g = IBScanner::instance();
  96. connect(g, SIGNAL(ibScannerTick(QList<IBResult*>)), this, SLOT(onIBScanTick(QList<IBResult*>)));
  97. g->start();
  98. //getdata();
  99. }
  100. double gety(int x)
  101. {
  102. int iRssi = abs(x);
  103. float power = (iRssi-46)/(10*3.25);
  104. return pow(10, power);
  105. }
  106. void MainWindow::onIBScanTick(QList<IBResult*> list) //画图槽函数
  107. {
  108. QListIterator<IBResult*> it(list);  //这是我接受到的数据
  109. while(it.hasNext())
  110. {
  111. IBResult* ib = it.next();
  112. QString mac = ib->mac;
  113. double tmp ;
  114. tmp = ib->rssi;  //取出我想画的数据
  115. QString majMin = QString::number(ib->major) + QString::number(ib->minor);
  116. //if(!ib_set.contains(majMin))    ib_set.insert(majMin);
  117. if(major_minor == majMin)
  118. {
  119. qInfo() <<  majMin << ": rssi =" << tmp;
  120. if(t <= 60)  //如果点数小于60
  121. {
  122. series0->append(t,tmp);  //把数据添加到series中
  123. scatseries0->append(t,tmp);
  124. series1->append(t,ib->dis);
  125. axisX->setRange(0,t);
  126. scatseries1->append(t,ib->dis);
  127. axisX2->setRange(0,t);  //注意此处,重新设置X轴范围,保持与像显示的点数一致
  128. //t++;
  129. }
  130. else //从传入第61个点开始,就开始滚动,把最早的点扔掉,加最新的一个点
  131. {
  132. //把数据前移一个单位,如果点的数量太多,这里消耗的时间也会很多
  133. QVector<QPointF> Points = series0->pointsVector();
  134. int i;
  135. for(i = 0;i< Points.size() - 1;i++)
  136. {
  137. Points[i] = QPoint(t+i,Points[i + 1].y());
  138. }
  139. Points[Points.size() - 1] = QPoint(t+i,tmp); //添加最新的点
  140. series0->replace(Points); //利用replace函数更新数据
  141. scatseries0->replace(Points);
  142. Points = series1->pointsVector();
  143. for(i = 0;i< Points.size() - 1;i++)
  144. {
  145. Points[i] = QPoint(t+i,Points[i + 1].y());
  146. }
  147. Points[Points.size() - 1] = QPoint(t+i,ib->dis);
  148. series1->replace(Points);
  149. scatseries1->replace(Points);
  150. axisX2->setRange(t,t+i);
  151. axisX->setRange(t,t+i);
  152. //t++;
  153. }
  154. if(tmp > maxy) maxy = tmp;
  155. if(tmp < miny) miny = tmp;
  156. axisY2->setRange(std::max(miny - 5,0) , maxy + 5);
  157. }
  158. /*        if(majMin == "1009135166")  //对不同的蓝牙画另外的线
  159. {
  160. qInfo() <<  majMin << ": rssi =" << tmp;
  161. if(t <= 60 )
  162. {
  163. series2->append(t,tmp);//gety(ib->rssi));
  164. scatseries2->append(t,tmp);//gety(ib->rssi));
  165. //t++;
  166. }
  167. else
  168. {
  169. QVector<QPointF> Points = series2->pointsVector();
  170. qInfo() << "size3 = " << Points.size();
  171. int i;
  172. for(i = 0;i< Points.size() - 1;i++)
  173. {
  174. Points[i] = QPoint(t+i,Points[i + 1].y());
  175. }
  176. Points[Points.size() - 1] = QPoint(t+i,tmp);//gety(ib->rssi));
  177. series2->replace(Points);
  178. scatseries2->replace(Points);
  179. if(tmp > maxy) maxy = tmp;
  180. if(tmp < miny) miny = tmp;
  181. }
  182. //t++;
  183. }
  184. */
  185. if(major_minor == majMin || majMin == "1009135166")
  186. {
  187. axisY2->setRange(miny, maxy + 5);
  188. t++;
  189. }
  190. }
  191. }
  192. MainWindow::~MainWindow()
  193. {
  194. delete ui;
  195. }

Qt Charts 动态实时折线图绘制相关推荐

  1. qchart折现图_Qt Charts 动态实时折线图绘制

    在Qt Charts发布之前, Qt比较著名两个画图插件是 qwt和Qcustom, 其中Qcustom较轻量,只需要在project 中包含qcustomplot.h 和 qcustomplot.c ...

  2. python画散点图程序-Python散点图与折线图绘制过程解析

    这篇文章主要介绍了Python散点图与折线图绘制过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在数据分析的过程中,经常需要将数据可视化,目 ...

  3. 两条纵坐标折线图绘制

    python 两条纵坐标折线图绘制 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你 ...

  4. g2.Chart折线图绘制

    目录 一.官方文档 二.g2.Chart折线图绘制 (一).引入g2.js (二).创建 div 图表容器 (三).绘图 1.静态数据 2.动态数据 一.官方文档 https://www.yuque. ...

  5. Matlab三维折线图绘制–surf 函数的使用

    Matlab三维折线图绘制–surf 函数的使用   最近在写毕业论文,整理数据需要绘制一个简单的三维图,简单做个分享! 先上结果图: 最后附上代码: clc,clear,close all; % f ...

  6. python使用matplotlib2D绘图库的折线图绘制小案例(方便matplotlib的学习理解)——随机数做幸运值,绘制一周的幸运趋势

    python使用matplotlib2D绘图库的折线图绘制小案例(方便matplotlib的学习理解)--随机数做幸运值,绘制一周的幸运趋势 QQ:3020889729 小蔡 小案例内容简介 实例 第 ...

  7. [转载] Python数据可视化库-Matplotlib——折线图绘制

    参考链接: Python Matplotlib数据可视化 plot折线图 # coding:utf-8 import pandas as pd import numpy as np from matp ...

  8. 使用matplotlib绘制折线图(绘制一天当中的气温变化)

    matplotlib绘制折线图 一.使用matplotlib绘制一天当中的气温变化 1.假设一天当中每隔两个小时(range(2,26,2))的气温分别是[15,13,14.5,17,20,25,26 ...

  9. matplotlib折线图绘制

    import matplotlib.pyplot as plt import matplotlib #设置图形框大小 plt.figure(figsize=(20,8),dpi=80) #绘制折线图' ...

最新文章

  1. Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析
  2. webpack流程图
  3. 教你玩转CSS表格(table)
  4. 阿里巴巴超大规模Kubernetes基础设施运维体系解读
  5. java 标准输入流 关闭 打开_java输出流关流疑问,以下这个程序的in和out是否要关闭?...
  6. Win下部署Django开发环境
  7. React Native 从入门到原理
  8. 若依前后端分离版本如何使用Swagger
  9. hdu 4005(边双连通)
  10. 文本分类——NaiveBayes
  11. (转) 穿越NAT总结
  12. 批量找关键词的软件-再也不用担心找不着 关键词了
  13. 基于北斗GNSS高精度形变位移监测系统
  14. 弹性碰撞次数与圆周率的关系 - 3Blue1Brown
  15. PTA 7-3 愿天下有情人都是失散多年的兄妹 (25 分)
  16. 星际迷航7:未来之城
  17. 失恋后明白的一些道理
  18. BottomNavigationView简单使用,增加小红点,增加中间操作按钮
  19. 给你的数据加上杠杆:文本增强技术的研究进展及应用实践
  20. 学习笔记|PSO粒子群算法(1)

热门文章

  1. Cris 的 Scala 笔记(五):流程控制
  2. Codeforces1221 B. Knights(构造)
  3. 从零吃透 Vue.js 框架,这里全部有!
  4. C语言入门题库——编写求圆面积和球体积的函数
  5. 手把手教您搭建AR应用开发环境
  6. [Java反序列化]CommonsCollections3利用链学习
  7. 图片转文字的app:智能、高效,你离大神就差一款清描!
  8. Win10蓝屏win32k power watchdog timeout 蓝屏代码0x0000019C
  9. 常用autojs命令
  10. 大数据ui设计师_为什么设计师应该使用真实数据