很重要--轉載聲明
- 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords
- 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。
一直說要講2.0.0版本,但老是想把1.3.2版本拿出來比較一下,這篇文章也不例外。QCustomPlot2.0.0beta版本比1.3.2release版本有一個很大的改進那就是分層繪製,所謂分層繪製就是把一張圖分幾張圖來繪製,最後在把這分開的幾張圖統一繪製到一張圖上,好比一張圖A,須要分開成3張圖B、C和D來繪製,當圖A須要從新繪製時,咱們一次判斷B、C和D是否須要從新繪製,若是不須要繪製的咱們直接把圖貼到A上,那就很大的減小了從新繪製的時間,而這部分時間實際上是沒有必要花費的。html
QCustomPlot默認提供了6個層,以下代碼所示,分別是:背景層、網格層、主層、座標軸層、圖例層和矩形選擇區域層。app
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")));
實現分層繪製的關鍵類QCPAbstractPaintBuffer,這是一個抽象基類,經過該類能夠拿到一個QCPPainter指針,而後繪製東西的時候,都會繪製在這個指針所指的繪圖設備上。QCPAbstractPaintBuffer類一共有3個子類,分別是QCPPaintBufferPixmap、QCPPaintBufferGlPbuffer和QCPPaintBufferGlFbo,這3個類分別使用了不一樣繪圖技術來實現分層繪製。默認使用的是QCPPaintBufferPixmap來繪製,若是想使用QCPPaintBufferGlPbuffer或者QCPPaintBufferGlFbo來繪製,首先要使用setOpenGl接口打開使用opengl開關,而後定義QCP_OPENGL_FBO宏來默認使用QCPPaintBufferGlFbo繪製,或者定義QCP_OPENGL_PBUFFER宏來讓默認使用QCPPaintBufferGlPbuffer方式繪製ide
下圖所示是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 8 QCPLayer(QCustomPlot* parentPlot, const QString &layerName); 9 virtual ~QCPLayer(); 10 11 // setters: 12 void setVisible(bool visible);//設置層是否可見 13 void setMode(LayerMode mode);//繪製時,painter使用模式 14 15 // non-virtual methods: 16 void replot();//從新繪製層 17 18 protected: 19 QCustomPlot *mParentPlot;//所在圖表 20 QString mName;//層名稱 21 int mIndex;//層序,決定繪製前後順序 22 QList<QCPLayerable*> mChildren;//層中全部元素 23 bool mVisible;//是否可見標記 24 LayerMode mMode;//繪製模式標記 25 26 // non-property members: 27 QWeakPointer<QCPAbstractPaintBuffer> mPaintBuffer;//繪製緩衝區 28 29 // non-virtual methods: 30 void draw(QCPPainter *painter);//使用painter繪製 31 void drawToPaintBuffer();//繪製到緩衝區 32 void addChild(QCPLayerable *layerable, bool prepend);//新增元素 33 void removeChild(QCPLayerable *layerable);//移除元素 34 };
如圖1中所示的黑色十字線,就是我在自定義層中繪製的,下面我將我實現的代碼貼出來post
圖1this
實現頭文件url
1 class CrossLinePlot : public QCPLayerable 2 { 3 Q_OBJECT 4 signals : 5 void DrawCrossLine(const QPoint & pos); 6 7 public: 8 CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot); 9 ~CrossLinePlot(); 10 11 public: 12 QString LayerName() const;//層名稱 13 void SetVisible(bool visible);//設置層是否繪製 14 15 void SetPen(const QPen & pen);/設置十字線畫筆 16 17 bool MouseButtonDown() const ; 18 bool GetLineVisible(QCP::LineState line) const; 19 void SetLineShow(QCP::LineState lines);//設置線是否顯示 20 21 //十字線同步註冊接口 22 bool RegisiterBortherLine(CrossLinePlot * line); 23 bool UnregisiterBortherLine(CrossLinePlot * line); 24 25 protected: 26 virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const{}; 27 virtual void draw(QCPPainter * painter); 28 29 private: 30 void DrawLine(QCPAxis * axis, Qt::Orientation orientation);//畫指定方向的座標軸十字線(嚴格來講應該是一部分,一條線) 31 void SyncLinePosition(const QPoint & pos, double x);//同步線位置 32 33 private slots: 34 void MouseMoveHandle(QMouseEvent * event); 35 36 private: 37 QScopedPointer<CrossLinePlotPrivate> d_ptr; 38 static std::vector<CrossLinePlot *> m_BrotherLine;//同步其餘十字線 39 };
實現文件spa
1 std::vector<CrossLinePlot *>CrossLinePlot::m_BrotherLine; 2 3 struct CrossLinePlotPrivate 4 { 5 QCP::LineStates m_bIsVisible; 6 bool m_bLeftButtonPress = false; 7 double m_dAxisXValue = -1; 8 QPoint m_MousePoint; 9 QCPPainter * m_pPainter = nullptr; 10 QPen m_Pen = QPen(Qt::black, 1, Qt::DashDotLine); 11 PlotCallback * m_pParentPlot = nullptr; 12 }; 13 14 CrossLinePlot::CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot) 15 : QCPLayerable(plot) 16 , d_ptr(new CrossLinePlotPrivate) 17 { 18 d_ptr->m_pParentPlot = basePlot; 19 mParentPlot->addLayer(LayerName()); 20 21 setLayer(LayerName()); 22 23 connect(mParentPlot, &QCustomPlot::mousePress, this, [this](QMouseEvent * event){ 24 if (event->button() & Qt::LeftButton) 25 { 26 d_ptr->m_bLeftButtonPress = true; 27 } 28 }); 29 connect(mParentPlot, &QCustomPlot::mouseRelease, this, [this](QMouseEvent * event){ 30 if (event->button() & Qt::LeftButton) 31 { 32 d_ptr->m_bLeftButtonPress = false; 33 } 34 }); 35 connect(mParentPlot, &QCustomPlot::mouseMove, this, &CrossLinePlot::MouseMoveHandle); 36 37 QVector<qreal> dashes; 38 qreal space = 4; 39 dashes << 3 << space << 9 << space; 40 d_ptr->m_Pen.setDashPattern(dashes); 41 } 42 43 CrossLinePlot::~CrossLinePlot() 44 { 45 46 } 47 48 QString CrossLinePlot::LayerName() const 49 { 50 return QStringLiteral("crossline"); 51 } 52 53 void CrossLinePlot::SetVisible(bool visible) 54 { 55 QCPLayer * layer = mParentPlot->layer(LayerName()); 56 if (layer) 57 { 58 layer->setVisible(visible); 59 } 60 } 61 62 void CrossLinePlot::SetPen(const QPen & pen) 63 { 64 d_ptr->m_Pen = pen; 65 } 66 67 bool CrossLinePlot::MouseButtonDown() const 68 { 69 return d_ptr->m_bLeftButtonPress; 70 } 71 72 bool CrossLinePlot::GetLineVisible(QCP::LineState line) const 73 { 74 switch (line) 75 { 76 case Qt::Horizontal: 77 return d_ptr->m_bIsVisible.testFlag(QCP::E_Horizontal); 78 break; 79 case Qt::Vertical: 80 return d_ptr->m_bIsVisible.testFlag(QCP::E_Vertical); 81 break; 82 } 83 84 return false; 85 } 86 87 void CrossLinePlot::SetLineShow(QCP::LineState lines) 88 { 89 switch (lines) 90 { 91 case QCP::E_NULL: 92 d_ptr->m_bIsVisible = QCP::E_NULL; 93 break; 94 case QCP::E_Horizontal: 95 d_ptr->m_bIsVisible = QCP::E_Horizontal; 96 break; 97 case QCP::E_Vertical: 98 d_ptr->m_bIsVisible = QCP::E_Vertical; 99 break; 100 case QCP::E_ALL: 101 d_ptr->m_bIsVisible = QCP::E_ALL; 102 break; 103 } 104 105 if (QCPLayer * layer = mParentPlot->layer(LayerName())) 106 { 107 layer->replot(); 108 } 109 110 if (d_ptr->m_bIsVisible == QCP::E_NULL) 111 { 112 for (CrossLinePlot * crossline : CrossLinePlot::m_BrotherLine) 113 { 114 if (crossline != this) 115 { 116 crossline->SyncLinePosition(QPoint(), d_ptr->m_dAxisXValue); 117 } 118 } 119 } 120 }
有興趣的同窗能夠自行看實現文件,代碼都不難理解.net
QCustomplot使用分享(四) QCPAbstractItem
這是QCustomPlot的第7篇文章了,按照我第二篇文章描述的那樣,從QCustomplot使用分享(二) 源碼解讀、QCustomplot使用分享(三) 圖 折線、參數曲線、蠟燭圖、柱狀圖、面積圖、QCustomplot使用分享(四) QCPAbstractItem、QCustomplot使用分享(五) 佈局、QCustomplot使用分享(六) 座標軸 網格線和QCustomplot使用分享(七) 層等這幾個方面對QCustomPlot作了一個分析,其實還有不少細節我沒有說到的地方。
雖然我使用QCustomPlot庫的時間不長,可是用了3天的時間我把QCustomPlot的使用或者說是心得記錄了下來,這幾篇文章在寫的過程當中,也是自我回憶、自我從新理解的一個過程,說實話寫完這幾篇文章我仍是收穫挺大的,最起碼能連貫的把這個源碼庫融合起來,如今在回想起這個庫我就會以爲腦子裏已經有了一個大概的圖,也能夠說是一幅畫,基本的功能模塊大致掌握,若是這時候給我一個需求,那我可能會更好的理解這個需求,更好的去在合適的地方更合理的完成這個需求。