QCustomplot使用分享(三) 图

一、可以实现的图

相对于其他绘制图表的第三方库来说,QCustomPlot算是比较轻量的,不仅仅能实现功能,而且二次开发比较容易。下面我们来具体说下他可以实现那些图

  1. QCPGraph:折线图,LineStyle枚举可以设置折线图绘制的风格,主要区别是两点间连线的方式,常规的方式就是直连,其他还有L型、Z型等,如图1所示,都是折线图,只是设置了不同的折线参数;QCPScatterStyle枚举用于设置节点类型,包括:圆形、三角形等,如图2所示。
  2. QCPBars:柱状图,如图3所示
  3. QCPFinancial:蜡烛图,主要用于展示股票k线图,如图4所示。
  4. 其他图表还包括:色谱图(QCPColorMap)、统计箱(QCPStatisticalBox)、参数曲线(QCPCurve),这几个图我就不单独贴图说明了,想看效果的同学可以去QCustomplot使用分享(一) 能做什么事查看。

二、效果预览

这里我在单独贴出来QCustomPlot可以实现的图表,或者点击QCustomplot使用分享(一) 能做什么事,这篇文章里有一个gif图,图中包含所有的图。

图1 折线图

图2 折线图

图3 柱状图

图4 蜡烛图

三、数据存储

因为本篇文章是基于QCustomPlot2.0.0beta版本分析,如果有同学发现和自己手头的源码有出入,首先看下源码版本是否一致,如果源码版本一致,但是和我说的有出入,欢迎指正。

一个关键的模板类QCPDataContainer,提供了一些基础的数据操作方法,例如:设置数据、新增数据、按键移除数据、清空、排序和查找等一些的方法,这个类出现的原因主要在于图和图仅仅是存储的数据类型不同,但是他们对这些数据操作时的接口基本相同,而这个类的功能就是把这些公有的接口提取出来,如果那个图表需要这样的数据存储,只需要用这个类来存储,类的模板参数指明具体的存储数据类型即可。

因为不同的表只是数据存储格式不一样,而他们对数据的接口操作已经被QCPDataContainer类抽象到一起了,比如:折线图数据存储类QCPGraphData、柱状图数据存储类QCPBarsData等,当他们使用数据存储的时候会像这样QCPDataContainer<QCPGraphData>和QCPDataContainer<QCPBarsData>来声明对象。

这个时候呢抽象还没有结束,因为所有的绘图类仅仅是提供的接口参数不一样,就像最终存储数据的结构不一样似的,比如折线图可能会像addData(QCPGraphData),柱状图可能会像addData(QCPBarsData),但是这些接口里实现的时候调用的操作完全是一样的,这个时候又出现了一个操作的抽象接口类QCPPlottableInterface1D,这个类的实现类是QCPAbstractPlottable1D,其中包含了一个QCPDataContainer指针,存储着具体的图表类型数据,他的声明可能会像下边这样

 1 template <class DataType>//该类在被继承的时候初始化该参数,一般设置为图表存储的数据类型
 2 class QCP_LIB_DECL QCPAbstractPlottable1D : public QCPAbstractPlottable, public QCPPlottableInterface1D
 3 {
 4     // No Q_OBJECT macro due to template class
 5
 6 public:
 7     QCPAbstractPlottable1D(QCPAxis *keyAxis, QCPAxis *valueAxis);
 8     virtual ~QCPAbstractPlottable1D();
 9
10     // virtual methods of 1d plottable interface:
11     virtual int dataCount() const;
12     virtual double dataMainKey(int index) const;
13     virtual double dataSortKey(int index) const;
14     virtual double dataMainValue(int index) const;
15     virtual QCPRange dataValueRange(int index) const;
16     virtual QPointF dataPixelPosition(int index) const;
17     virtual bool sortKeyIsMainKey() const;
18     virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const;
19     virtual int findBegin(double sortKey, bool expandedRange = true) const;
20     virtual int findEnd(double sortKey, bool expandedRange = true) const;
21
22     // virtual methods:
23     virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details = 0) const;
24     virtual QCPPlottableInterface1D *interface1D() { return this; }
25
26 protected:
27     // property members:
28     QSharedPointer<QCPDataContainer<DataType> > mDataContainer;//数据存储容器,提供了绝大多数的操作
29
30     // helpers for subclasses:
31     void getDataSegments(QList<QCPDataRange> &selectedSegments, QList<QCPDataRange> &unselectedSegments) const;
32     void drawPolyline(QCPPainter *painter, const QVector<QPointF> &lineData) const;
33
34 private:
35     Q_DISABLE_COPY(QCPAbstractPlottable1D)
36 };

说到这里可能大家还是迷迷糊糊,那么接下来我们就上一个QCPGraph类的添加数据接口代码展示,大家一看就一目了然了。虽然QCPDataContainer容器类给我们提供了很多接口,但是有些接口的返回值我们是拿不到的,比如说begine和end指针地址,但是QCPPlottableInterface1D类帮助我们拿到了,因为我们所有的图表类都是该类的子类,我们都可以使用其中的方法,具体的可以自行查看QCPPlottableInterface1D接口类的实现类QCPAbstractPlottable1D

 1 void QCPGraph::addData(const QVector<double> &keys, const QVector<double> &values, bool alreadySorted)
 2 {
 3     if (keys.size() != values.size())
 4         qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size();
 5     const int n = qMin(keys.size(), values.size());
 6     QVector<QCPGraphData> tempData(n);
 7     QVector<QCPGraphData>::iterator it = tempData.begin();
 8     const QVector<QCPGraphData>::iterator itEnd = tempData.end();
 9     int i = 0;
10     while (it != itEnd)
11     {
12         it->key = keys[i];
13         it->value = values[i];
14         ++it;
15         ++i;
16     }
17     mDataContainer->add(tempData, alreadySorted); // 这个add接口其实就是QCPDataContainer类提供的,
18 }   

上边的这个数据存储抽象其实在QCustomPlot1.3.2发布版本中是没有的,不过我觉着这一部分做的挺不错的,不仅简化了代码,而且可维护性更强。

四、一个简单的示例

QCustomPlot的接口封装还是比较易懂的,那我在这里也就不一一举例说明每个图表的使用方法了,下面是折线图的简单用法,对应的效果图是图1

 1     ui.widget_12->legend->setVisible(true);
 2     ui.widget_12->legend->setFont(QFont("Helvetica", 9));
 3     QPen pen;
 4     QStringList lineNames;//设置图例的文本
 5     lineNames << "lsNone" << "lsLine" << "lsStepLeft" << "lsStepRight" << "lsStepCenter" << "lsImpulse";
 6     // add graphs with different line styles:
 7     for (int i = QCPGraph::lsNone; i <= QCPGraph::lsImpulse; ++i)
 8     {
 9         ui.widget_12->addGraph();
10         pen.setColor(QColor(qSin(i * 1 + 1.2) * 80 + 80, qSin(i*0.3 + 0) * 80 + 80, qSin(i*0.3 + 1.5) * 80 + 80));
11         ui.widget_12->graph()->setPen(pen);
12         ui.widget_12->graph()->setName(lineNames.at(i - QCPGraph::lsNone));
13         ui.widget_12->graph()->setLineStyle((QCPGraph::LineStyle)i);//设置线性
14         ui.widget_12->graph()->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));//设置每个节点数据绘制风格,默认是空,这里设置为空心圆
15         // generate data:
16         QVector<double> x(15), y(15);
17         for (int j = 0; j < 15; ++j)
18         {
19             x[j] = j / 15.0 * 5 * 3.14 + 0.01;
20             y[j] = 7 * qSin(x[j]) / x[j] - (i - QCPGraph::lsNone) * 5 + (QCPGraph::lsImpulse) * 5 + 2;
21         }
22         ui.widget_12->graph()->setData(x, y);
23         ui.widget_12->graph()->rescaleAxes(true);//坐标轴自适应
24     }
25     // zoom out a bit:
26     ui.widget_12->yAxis->scaleRange(1.1, ui.widget_12->yAxis->range().center());
27     ui.widget_12->xAxis->scaleRange(1.1, ui.widget_12->xAxis->range().center());
28     // set blank axis lines:
29     ui.widget_12->xAxis->setTicks(false);//x轴不显示刻度
30     ui.widget_12->yAxis->setTicks(true);//y轴显示刻度
31     ui.widget_12->xAxis->setTickLabels(false);//x轴不显示文本
32     ui.widget_12->yAxis->setTickLabels(true);//y轴显示文本
33     // make top right axes clones of bottom left axes:
34     ui.widget_12->axisRect()->setupFullAxesBox();一个默认的坐标轴矩形配置,包括:顶部坐标轴跟随底部坐标轴同步、右侧坐标轴跟随左侧坐标轴同步,不仅仅是坐标轴范围跟随同步,包括文本精度、文本格式、坐标轴类型、是否自动生成刻度、刻度间距等等。

五、相关文章

QCustomplot使用分享(一) 能做什么事

QCustomplot使用分享(二) 源码解读

时间: 2024-10-14 12:09:21

QCustomplot使用分享(三) 图的相关文章

QCustomplot使用分享(五) 布局

一.历史对比 关于QCPLayoutElement这个元素的讲解之前,我想先对1.3.2release版本和2.0.0beta版本的该元素做以简单的对比介绍,首先,1.3.2release版本时,鼠标单击时,如果按下的位置是一个布局元素,那么QCustomPlot首先会把这个事件回调给该被点击的元素,并且mouse系列的方法都是这样传递给QCPLayoutElement对象,该布局元素的声明会像这样QPointer<QCPLayoutElement> mMouseEventElement:但是

QCustomplot使用分享(二) 源码解读

一.头文件概述 从这篇文章开始,我们将正式的进入到QCustomPlot的实践学习中来,首先我们先来学习下QCustomPlot的类图,如果下载了QCustomPlot源码的同学可以自己去QCustomPlot的目录下documentation/qcustomplot下寻找一个名字叫做index.html的文件,将其在浏览器中打开,也是可以找到这个库的类图.如图1所示,是组成一个QCustomPlot类图的可能组成形式. 一个图表(QCustomPlot):包含一个或者多个图层.一个或多个ite

QCustomplot使用分享(四) QCPAbstractItem

一.是什么 说起图,大家一下就可能想到折线图.柱状图和饼图等,但是除了这些显眼的东西以外其实还有很多东西辅助的存在着,有了这些辅助的东西图才会看起来有意义,或者说更加的真实.有说服力.这些东西都包括那些呢?首先坐标轴肯定是不能少了的,还有网格线.图例和示意说明等.这一节我们就重点来围绕这个示意说明也就是QCPAbstractItem来做以解释 二.效果图 这里我将首先贴张效果图,主要是为了展示QCPAbstractItem的用途,有需要的同学可以深入的了解下.图上出了一条折线之外,还有坐标轴.网

QCustomplot使用分享(七) 层(完结)

一.分层绘制 一直说要讲2.0.0版本,但总是想把1.3.2版本拿出来比较一下,这篇文章也不例外.QCustomPlot2.0.0beta版本比1.3.2release版本有一个很大的改进那就是分层绘制,所谓分层绘制就是把一张图分几张图来绘制,最后在把这分开的几张图统一绘制到一张图上,比如一张图A,需要分开成3张图B.C和D来绘制,当图A需要重新绘制时,我们一次判断B.C和D是否需要重新绘制,如果不需要绘制的我们直接把图贴到A上,那就很大的减少了重新绘制的时间,而这部分时间其实是没有必要花费的.

QCustomplot使用分享(六) 坐标轴和网格线

一.概述 前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了,但是如果想要做到高度的控制图表,那么坐标轴将是很重要的一部分,因为坐标轴就是图表的一个参考系,没有了参考系那么一切都是天方夜谭.关于QCustomPlot的坐标轴我还是会按照之前的套路,首先对比1.3.2版本和2.0.0beta版本,然后在深入的去分析坐标轴使用. 二.历史版本对比 首先我需要和大家伙说明下,我个人觉着在QCustomPlot的定制过程中,坐标轴定制算是比较困难的,因为坐标

QCustomplot使用分享(九) 绘制图表-多功能游标

目录 一.概述 二.效果图 三.源码讲解 1.源码结构 2.头文件 3.添加游标 4.监测移动 5.移动游标 6.其他函数 四.测试方式 1.测试工程 2.测试文件 3.测试代码 五.相关文章 六.总结 七.关于美化 原文链接:QCustomplot使用分享(九) 绘制图表-多功能游标 一.概述 上一篇文章QCustomplot使用分享(八) 层(完结)讲述了第一篇QCustomPlot控件的使用,主要是展示了多维度折线图,并且有一个简单的游标展示效果.本篇文章是在上一篇文章的基础上进行的功能加

开源分享三(炫酷的Android Loading动画)

开源分享三(炫酷的Android Loading动画) 分享GitHub上的一些Loading,为了提升产品用户体验,一个好的Loading必然是不可缺少的,对于一些耗时需要用户等待的页面来说会转移用户注意力,不会显得那么烦躁,所以你可以看到市面上一些App中的各种各样的Loading动画,从这些实现思路上可以打开你们自己的思维,没准也会有创新的Loading动画出现. android-shapeLoadingView 新版58同城加载页面动画. CircleProgress 一个效果很酷炫很创

QCustomplot使用分享(一) 能做什么事

一.QCustomPlot简介 之前在Qt之自绘制饼图这篇文章的说明中我简单的描述了下目前依赖于qt的第三方绘图库,此后我会针对自己使用QCustomPlot的情况做一总结,以方便大家参考 QCustomPlot的官方网址:Qt Plotting Widget QCustomPlot - Introduction QCustomPlot的源码只有2个文件,所以添加供自己的工程师特别方便,或者你自己把这两个文件编译成静态库.动态库的形式都行. 二.效果预览 如图1是我自己把官方的示例代码融合在一起

自了法师全集 | 无量寿经科注第四回学习班分享三十篇

释自了法师 净土指归 1月28日 南无阿弥陀佛 欢迎点击上方关注“净土指归” 自了法师 无量寿经科注第四回学习班分享三十篇全集 目录 生死心不切,若真为生死之心不发,一切开示皆为戏论 凡修净业,以决志求生西方为本 佛一边念,生死爱根一边长 重新认识净土法门 时时作临终想 念佛法门,首为凡夫 常念不绝,则得道捷 日暮途远 摄耳谛听 历代祖师示真信切愿 是心是佛,是心作佛 印光大师述<无量寿经>缘起 都摄六根,净念相继 欲报亲恩唯念佛 ——浅谈祭祖最重要的内涵 不信佛.不信佛力 ——从占察忏现象引