当前位置:   article > 正文

QCustomplot 层_in member function ‘void qcplayer::setmode(qcplaye

in member function ‘void qcplayer::setmode(qcplayer::layermode)’:

一、分层绘制

    一直说要讲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个层,如下代码所示,分别是:背景层、网格层、主层、坐标轴层、图例层和矩形选择区域层。

  1. mLayers.append(new QCPLayer(this, QLatin1String("background")));
  2. mLayers.append(new QCPLayer(this, QLatin1String("grid")));
  3. mLayers.append(new QCPLayer(this, QLatin1String("main")));
  4. mLayers.append(new QCPLayer(this, QLatin1String("axes")));
  5. mLayers.append(new QCPLayer(this, QLatin1String("legend")));
  6. 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图层类的部分头文件,代码里的大多数成员变量和成员方法我都给出了注释,大家看看并仔细揣摩一下,应该就基本能理解了。

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

四、自定义层

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

图1

    实现头文件

  1. class CrossLinePlot : public QCPLayerable
  2. {
  3. Q_OBJECT
  4. signals :
  5. void DrawCrossLine(const QPoint & pos);
  6. public:
  7. CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot);
  8. ~CrossLinePlot();
  9. public:
  10. QString LayerName() const;//层名称
  11. void SetVisible(bool visible);//设置层是否绘制
  12. void SetPen(const QPen & pen);/设置十字线画笔
  13. bool MouseButtonDown() const ;
  14. bool GetLineVisible(QCP::LineState line) const;
  15. void SetLineShow(QCP::LineState lines);//设置线是否显示
  16. //十字线同步注册接口
  17. bool RegisiterBortherLine(CrossLinePlot * line);
  18. bool UnregisiterBortherLine(CrossLinePlot * line);
  19. protected:
  20. virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const{};
  21. virtual void draw(QCPPainter * painter);
  22. private:
  23. void DrawLine(QCPAxis * axis, Qt::Orientation orientation);//画指定方向的坐标轴十字线(严格来说应该是一部分,一条线)
  24. void SyncLinePosition(const QPoint & pos, double x);//同步线位置
  25. private slots:
  26. void MouseMoveHandle(QMouseEvent * event);
  27. private:
  28. QScopedPointer<CrossLinePlotPrivate> d_ptr;
  29. static std::vector<CrossLinePlot *> m_BrotherLine;//同步其他十字线
  30. };

    实现文件

  1. std::vector<CrossLinePlot *>CrossLinePlot::m_BrotherLine;
  2. struct CrossLinePlotPrivate
  3. {
  4. QCP::LineStates m_bIsVisible;
  5. bool m_bLeftButtonPress = false;
  6. double m_dAxisXValue = -1;
  7. QPoint m_MousePoint;
  8. QCPPainter * m_pPainter = nullptr;
  9. QPen m_Pen = QPen(Qt::black, 1, Qt::DashDotLine);
  10. PlotCallback * m_pParentPlot = nullptr;
  11. };
  12. CrossLinePlot::CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot)
  13. : QCPLayerable(plot)
  14. , d_ptr(new CrossLinePlotPrivate)
  15. {
  16. d_ptr->m_pParentPlot = basePlot;
  17. mParentPlot->addLayer(LayerName());
  18. setLayer(LayerName());
  19. connect(mParentPlot, &QCustomPlot::mousePress, this, [this](QMouseEvent * event){
  20. if (event->button() & Qt::LeftButton)
  21. {
  22. d_ptr->m_bLeftButtonPress = true;
  23. }
  24. });
  25. connect(mParentPlot, &QCustomPlot::mouseRelease, this, [this](QMouseEvent * event){
  26. if (event->button() & Qt::LeftButton)
  27. {
  28. d_ptr->m_bLeftButtonPress = false;
  29. }
  30. });
  31. connect(mParentPlot, &QCustomPlot::mouseMove, this, &CrossLinePlot::MouseMoveHandle);
  32. QVector<qreal> dashes;
  33. qreal space = 4;
  34. dashes << 3 << space << 9 << space;
  35. d_ptr->m_Pen.setDashPattern(dashes);
  36. }
  37. CrossLinePlot::~CrossLinePlot()
  38. {
  39. }
  40. QString CrossLinePlot::LayerName() const
  41. {
  42. return QStringLiteral("crossline");
  43. }
  44. void CrossLinePlot::SetVisible(bool visible)
  45. {
  46. QCPLayer * layer = mParentPlot->layer(LayerName());
  47. if (layer)
  48. {
  49. layer->setVisible(visible);
  50. }
  51. }
  52. void CrossLinePlot::SetPen(const QPen & pen)
  53. {
  54. d_ptr->m_Pen = pen;
  55. }
  56. bool CrossLinePlot::MouseButtonDown() const
  57. {
  58. return d_ptr->m_bLeftButtonPress;
  59. }
  60. bool CrossLinePlot::GetLineVisible(QCP::LineState line) const
  61. {
  62. switch (line)
  63. {
  64. case Qt::Horizontal:
  65. return d_ptr->m_bIsVisible.testFlag(QCP::E_Horizontal);
  66. break;
  67. case Qt::Vertical:
  68. return d_ptr->m_bIsVisible.testFlag(QCP::E_Vertical);
  69. break;
  70. }
  71. return false;
  72. }
  73. void CrossLinePlot::SetLineShow(QCP::LineState lines)
  74. {
  75. switch (lines)
  76. {
  77. case QCP::E_NULL:
  78. d_ptr->m_bIsVisible = QCP::E_NULL;
  79. break;
  80. case QCP::E_Horizontal:
  81. d_ptr->m_bIsVisible = QCP::E_Horizontal;
  82. break;
  83. case QCP::E_Vertical:
  84. d_ptr->m_bIsVisible = QCP::E_Vertical;
  85. break;
  86. case QCP::E_ALL:
  87. d_ptr->m_bIsVisible = QCP::E_ALL;
  88. break;
  89. }
  90. if (QCPLayer * layer = mParentPlot->layer(LayerName()))
  91. {
  92. layer->replot();
  93. }
  94. if (d_ptr->m_bIsVisible == QCP::E_NULL)
  95. {
  96. for (CrossLinePlot * crossline : CrossLinePlot::m_BrotherLine)
  97. {
  98. if (crossline != this)
  99. {
  100. crossline->SyncLinePosition(QPoint(), d_ptr->m_dAxisXValue);
  101. }
  102. }
  103. }
  104. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/297489
推荐阅读
相关标签
  

闽ICP备14008679号