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使用分享(二) 源碼解讀

 

 

如果您覺得文章不錯,不妨給個 打賞,寫作不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明

  1. 本站文章無特別說明,皆為原創,版權所有,轉載時請用鏈接的方式,給出原文出處。同時寫上原作者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目的。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM