文章目录

  • 一、分层绘制
  • 二、QCustomPlot的层
  • 三、QCPLayer
  • 四、自定义层
  • 五、相关文章
  • 六、总结
  • 七、示例下载

一、分层绘制

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

二、QCustomPlot的层

QCustomPlot默认提供了6个层,如下代码所示,分别是:背景层、网格层、主层、坐标轴层、图例层和矩形选择区域层。

mLayers.append(new QCPLayer(this, QLatin1String("background")));
mLayers.append(new QCPLayer(this, QLatin1String("grid")));
mLayers.append(new QCPLayer(this, QLatin1String("main")));
mLayers.append(new QCPLayer(this, QLatin1String("axes")));
mLayers.append(new QCPLayer(this, QLatin1String("legend")));
mLayers.append(new QCPLayer(this, QLatin1String("overlay")));
  • 背景层:绘制背景图
  • 网格层:绘制网格线,每一个坐标轴对应一个网格对象
  • 主层:绘制图表
  • 坐标轴层:绘制坐标轴
  • 图例层:绘制图例
  • overlay层:绘制最上层的东西,这一层在1.3.2版本时没有。鼠标选择矩形框在此层绘制。可以参考QCustomplot使用分享(五) 布局文章中图1

实现分层绘制的关键类QCPAbstractPaintBuffer,这是一个抽象基类,通过该类可以拿到一个QCPPainter指针,然后绘制东西的时候,都会绘制在这个指针所指的绘图设备上。QCPAbstractPaintBuffer类一共有3个子类,分别是QCPPaintBufferPixmap、QCPPaintBufferGlPbuffer和QCPPaintBufferGlFbo,这3个类分别使用了不同绘图技术来实现分层绘制。默认使用的是QCPPaintBufferPixmap来绘制,如果想使用QCPPaintBufferGlPbuffer或者QCPPaintBufferGlFbo来绘制,首先要使用setOpenGl接口打开使用opengl开关,然后定义QCP_OPENGL_FBO宏来默认使用QCPPaintBufferGlFbo绘制,或者定义QCP_OPENGL_PBUFFER宏来让默认使用QCPPaintBufferGlPbuffer方式绘制

三、QCPLayer

下图所示是QCPLayer图层类的部分头文件,代码里的大多数成员变量和成员方法我都给出了注释,大家看看并仔细揣摩一下,应该就基本能理解了。

class QCP_LIB_DECL QCPLayer : public QObject
{enum LayerMode {//分层绘制原理lmLogical   ///< Layer is used only for rendering order, and shares paint buffer with all other adjacent logical layers., lmBuffered ///< Layer has its own paint buffer and may be replotted individually (see \ref replot).};QCPLayer(QCustomPlot* parentPlot, const QString &layerName);virtual ~QCPLayer();// setters:void setVisible(bool visible);//设置层是否可见void setMode(LayerMode mode);//绘制时,painter使用模式// non-virtual methods:void replot();//重新绘制层protected:QCustomPlot *mParentPlot;//所在图表QString mName;//层名称int mIndex;//层序,决定绘制先后顺序QList<QCPLayerable*> mChildren;//层中所有元素bool mVisible;//是否可见标记LayerMode mMode;//绘制模式标记// non-property members:QWeakPointer<QCPAbstractPaintBuffer> mPaintBuffer;//绘制缓冲区// non-virtual methods:void draw(QCPPainter *painter);//使用painter绘制void drawToPaintBuffer();//绘制到缓冲区void addChild(QCPLayerable *layerable, bool prepend);//新增元素void removeChild(QCPLayerable *layerable);//移除元素
};

四、自定义层

如图1中所示的黑色十字线,就是我在自定义层中绘制的,下面我将我实现的代码贴出来

实现头文件

class CrossLinePlot : public  QCPLayerable
{Q_OBJECT
signals :void DrawCrossLine(const QPoint & pos);public:CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot);~CrossLinePlot();public:QString LayerName() const;//层名称void SetVisible(bool visible);//设置层是否绘制void SetPen(const QPen & pen);/设置十字线画笔bool MouseButtonDown() const ;bool GetLineVisible(QCP::LineState line) const;void SetLineShow(QCP::LineState lines);//设置线是否显示//十字线同步注册接口bool RegisiterBortherLine(CrossLinePlot * line);bool UnregisiterBortherLine(CrossLinePlot * line);protected:virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const{};virtual void draw(QCPPainter * painter);private:void DrawLine(QCPAxis * axis, Qt::Orientation orientation);//画指定方向的坐标轴十字线(严格来说应该是一部分,一条线)void SyncLinePosition(const QPoint & pos, double x);//同步线位置private slots:void MouseMoveHandle(QMouseEvent * event);private:QScopedPointer<CrossLinePlotPrivate> d_ptr;static std::vector<CrossLinePlot *> m_BrotherLine;//同步其他十字线
};

实现文件

std::vector<CrossLinePlot *>CrossLinePlot::m_BrotherLine;struct CrossLinePlotPrivate
{QCP::LineStates m_bIsVisible;bool m_bLeftButtonPress = false;double m_dAxisXValue = -1;QPoint m_MousePoint;QCPPainter * m_pPainter = nullptr;QPen m_Pen = QPen(Qt::black, 1, Qt::DashDotLine);PlotCallback * m_pParentPlot = nullptr;
};CrossLinePlot::CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot): QCPLayerable(plot), d_ptr(new CrossLinePlotPrivate)
{d_ptr->m_pParentPlot = basePlot;mParentPlot->addLayer(LayerName());setLayer(LayerName());connect(mParentPlot, &QCustomPlot::mousePress, this, [this](QMouseEvent * event){if (event->button() & Qt::LeftButton){d_ptr->m_bLeftButtonPress = true;}});connect(mParentPlot, &QCustomPlot::mouseRelease, this, [this](QMouseEvent * event){if (event->button() & Qt::LeftButton){d_ptr->m_bLeftButtonPress = false;}});connect(mParentPlot, &QCustomPlot::mouseMove, this, &CrossLinePlot::MouseMoveHandle);QVector<qreal> dashes;qreal space = 4;dashes << 3 << space << 9 << space;d_ptr->m_Pen.setDashPattern(dashes);
}CrossLinePlot::~CrossLinePlot()
{}QString CrossLinePlot::LayerName() const
{return QStringLiteral("crossline");
}void CrossLinePlot::SetVisible(bool visible)
{QCPLayer * layer = mParentPlot->layer(LayerName());if (layer){layer->setVisible(visible);}
}void CrossLinePlot::SetPen(const QPen & pen)
{d_ptr->m_Pen = pen;
}bool CrossLinePlot::MouseButtonDown() const
{return d_ptr->m_bLeftButtonPress;
}bool CrossLinePlot::GetLineVisible(QCP::LineState line) const
{switch (line){case Qt::Horizontal:return d_ptr->m_bIsVisible.testFlag(QCP::E_Horizontal);break;case Qt::Vertical:return d_ptr->m_bIsVisible.testFlag(QCP::E_Vertical);break;}return false;
}void CrossLinePlot::SetLineShow(QCP::LineState lines)
{switch (lines){case QCP::E_NULL:d_ptr->m_bIsVisible = QCP::E_NULL;break;case QCP::E_Horizontal:d_ptr->m_bIsVisible = QCP::E_Horizontal;break;case QCP::E_Vertical:d_ptr->m_bIsVisible = QCP::E_Vertical;break;case QCP::E_ALL:d_ptr->m_bIsVisible = QCP::E_ALL;break;}if (QCPLayer * layer = mParentPlot->layer(LayerName())){layer->replot();}if (d_ptr->m_bIsVisible == QCP::E_NULL){for (CrossLinePlot * crossline : CrossLinePlot::m_BrotherLine){if (crossline != this){crossline->SyncLinePosition(QPoint(), d_ptr->m_dAxisXValue);}}}
}

有兴趣的同学可以自行看实现文件,代码都不难理解

五、相关文章

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

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

QCustomplot使用分享(三) 图

QCustomplot使用分享(四) QCPAbstractItem

QCustomplot使用分享(五) 布局

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

六、总结

这是QCustomPlot的第7篇文章了,按照我第二篇文章描述的那样,从QCustomplot使用分享(二) 源码解读、QCustomplot使用分享(三) 图 折线、参数曲线、蜡烛图、柱状图、面积图、QCustomplot使用分享(四) QCPAbstractItem、QCustomplot使用分享(五) 布局、QCustomplot使用分享(六) 坐标轴 网格线和QCustomplot使用分享(七) 层等这几个方面对QCustomPlot做了一个分析,其实还有很多细节我没有说到的地方。

虽然我使用QCustomPlot库的时间不长,但是用了3天的时间我把QCustomPlot的使用或者说是心得记录了下来,这几篇文章在写的过程中,也是自我回忆、自我重新理解的一个过程,说实话写完这几篇文章我还是收获挺大的,最起码能连贯的把这个源码库融合起来,现在在回想起这个库我就会觉得脑子里已经有了一个大概的图,也可以说是一幅画,基本的功能模块大体掌握,如果这时候给我一个需求,那我可能会更好的理解这个需求,更好的去在合适的地方更合理的完成这个需求。

七、示例下载

基于QCustomPlot1.3.2的二次开发

基于QCustomPlot2.0.0的二次开发

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!

很重要–转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


QCustomplot使用分享(四) QCPAbstractItem相关推荐

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

    文章目录 一.概述 二.历史版本对比 三.坐标轴 四.网格线 五.简单的示例 六.相关文章 一.概述 前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了, ...

  2. 1000道Python题库系列分享四(40道)

    热烈庆祝2018年2月董付国老师<Python程序设计(第2版)>出版18个月第5次印刷,<Python可以这样学>出版12个月第5次印刷,系列教材<Python程序设计 ...

  3. 四川大学计算机学院2016级毕业生,小猿分享 | 四年磨一剑:计算机学院2016级优秀毕业生高含宁专访...

    原标题:小猿分享 | 四年磨一剑:计算机学院2016级优秀毕业生高含宁专访 华大青年讯(通讯员 蒋政科)2016级优秀毕业生高含宁,大一时确定了读研的想法,在基础课和专业课上严格要求自己,打下了坚实的 ...

  4. 怎么将file转换为html,怎么将PDF文件转换为HTML?分享四种实用方法!

    原标题:怎么将PDF文件转换为HTML?分享四种实用方法! 在我们日常学习和日常工作中,如果想要将PDF文件转换为HTML文件要怎么办呢?随着需求的增加,我们需要会的技能也要增加了.不止要将PDF文件 ...

  5. 英语学习经验分享(四六级、竞赛、口语)

    英语学习经验分享(四六级.竞赛.口语) 什么时候开始下决心好好学英语的,自己又经历了哪些苦逼事儿??? Listening Speaking 英语竞赛有哪些需要参加??? 全国大学生英语竞赛 河南省翻 ...

  6. Flink 从0到1学习—— 分享四本 Flink 国外的书和二十多篇 Paper 论文

    前言 之前也分享了不少自己的文章,但是对于 Flink 来说,还是有不少新入门的朋友,这里给大家分享点 Flink 相关的资料(国外数据 pdf 和流处理相关的 Paper),期望可以帮你更好的理解 ...

  7. 如何利用短视频做营销?分享四个小方法,有需求的可尝试

    如何利用短视频做营销?分享四个小方法,有需求的可尝试 很多人做短视频的最主要目的其实并不仅仅只是为了分享生活中的趣事,而是想着如果可以利用短视频来做营销,获得收益,自然会更好.那么,我们可以如何利用短 ...

  8. 如何给电脑文件加密?分享四种方法!

    想要给文件设置加密,防止他人查看自己的文件,分享四种方法给电脑文件加密. 一:隐藏文件 如果不想给文件设置密码,我们可以将文件隐藏起来,这样设置之后,文件就不会再显示在文件夹里了,想要隐藏文件,我们只 ...

  9. 美食类短视频如何定位?分享四种类型,选对适合的方向很重要

    美食类短视频如何定位?分享四种类型,选对适合的方向很重要 人人都是"干饭人",所以美食类短视频从来都是不会缺少粉丝的.但是这并不说明做美食类短视频的小伙伴们可以随心所欲的做内容,比 ...

最新文章

  1. 如何在 Outlook 中使用外出时的助理程序
  2. 多个ajax执行混乱问题
  3. CSS 的三个特性:层叠性、继承性、优先级
  4. 百度智能云人脸库的创建与使用
  5. 点云数据(point cloud)
  6. 测试用例(功能用例)——资产申购、统计报表
  7. 常用视频像素格式 YUV422 YUV420
  8. 你们要的后台管理系统全套,今天它来了【开源推荐】
  9. iOS GPUImage 自定义美颜滤镜
  10. 全民一起VBA提高篇 第三十二回 Select 简化分枝结构,静态变量坐看沧海桑田
  11. 【创新实训】 爬虫开发记录(3):爬取时光网详情页
  12. 西门子PLC1200模拟量功能案例
  13. VMware虚拟机装系统出现Units specified dont exist解决办法
  14. 产品故事|你所不知道的语雀画板
  15. module blacklist
  16. Cisco 7600系列Supervisor Engine 720-3BXL
  17. 纪念品分组java_纪念品分组 (Java代码)
  18. 为什么现在深度学习才流行起来?
  19. 双数组Trie的一种实现
  20. Discuz 论坛设置发帖最大字数

热门文章

  1. iOS bundle format unrecognized, invalid, or unsuitable
  2. C#模拟PrtScn实现截屏预备知识--keybd_event使用方法
  3. 爆款电商直播间如何打造?
  4. windows10屏幕录制_如何在Windows 10中拍摄屏幕截图
  5. 青蛙变态跳+python
  6. java 加背景颜色_Java 给Word文档添加背景颜色
  7. 使用Selenium爬取淘宝商品(绕过登录页面)
  8. Ubuntu 20.04 时间校正
  9. PyTorch + Ray Tune 调参
  10. T5 -运动鞋品牌识别