Continued qcustomplot advanced axis application adds graphics section

1. How to manage axisRect

2. How to manage graph

3. Get graphics setting data

The code is as follows:

#ifndef MPLOT_H
#define MPLOT_H

#include "qcustomplot.h"
#include "datdefine.h"

class QCPMarginGroup;
class QCPGraph;
class QCPGraphData;

class MPlot : public QCustomPlot
{
    Q_OBJECT
public:
    explicit MPlot(QWidget *parent = nullptr);
    ~MPlot();

    /**
     * @brief setMInteractionType sets the user-graph interaction type
     * @param iType mNone->empty mode, mDefault->default mode, mSelect->select mode
     */
    void setMInteractionType(MInteraction iType);

    /**
     * @brief addAxisRect Advanced axis rectangle addition
     * @param strY y-axis name
     * @param strX x-axis name
     * @param strTitile rectangle title
     * @return currently added rectangle
     */
    void addAxisRect(const QString & amp;strY, const QString & amp;strX, const QString & amp;strTitile, \
                     int graphCnt, Qt::Orientation ori = Qt::Horizontal, MPlotTableType tableType = mGraph);

    /**
     * @brief addGraphByRect adds graphics to the current rectangle
     * @param rect
     * @param tableType
     * @return
     */
    bool addGraphsOnRect(QCPAxisRect *rect, MPlotTableType tableType = mGraph);

    /**
     * @brief resetGraphsByRect reset graphics
     * @param rect
     */
    void resetGraphsByRect(QCPAxisRect *rect);

    /**
     * @brief rectCount Get the number of rectangles
     * @return
     */
    int rectCount() const;
    /**
     * @brief axisRectByIndex Find rectangle by serial number
     * @param index
     * @return
     */
    QCPAxisRect * axisRectByIndex(const int index);

    /**
     * @brief usingGraphs Gets the number of used graphics and unused graphics through the rectangle serial number
     * @param nRectIndex
     * @param item
     */
    void usingGraphs(int nRectIndex, QPair<int, int> & amp;item);

    /**
     * @brief graphsCount Get the current number of rectangular graphics
     * @param nRectIndex
     * @return
     */
    int graphsCount(const int nRectIndex);

    /**
     * @brief getOneUnseGraph Gets the next graph of the current rectangle
     * @param nRectIndex rectangle serial number
     * @return
     */
    QCPGraph* getOneUnseGraph(int nRectIndex);

    /**
     * @brief clearData clears the data under all graphics of the current rectangle
     * @param nRectIndex
     */
    void clearData(const int nRectIndex);

    /**
     * @brief setData Take out the graphics from the current rectangle and set the data
     * @param nRectIndex
     * @param indexes
     * @param keys
     * @param values
     */
    void setData(int nRectIndex,QVector<int> indexes, QVector<double>keys, QVector<double> values);

    //rpImmediateRefresh: Replots immediately and repaints the widget immediately by calling QWidget::repaint() after the replot
    //rpQueuedRefresh: Replots immediately, but queues the widget repaint, by calling QWidget::update() after the replot. This way multiple redundant widget repaints can be avoided.
    //rpRefreshHint: Whether to use immediate or queued refresh depends on whether the plotting hint \ref QCP::phImmediateRefresh is set, see \ref setPlottingHints.
    //rpQueuedReplot: Queues the entire replot for the next event loop iteration. This way multiple redundant replots can be avoided. The actual replot is then done with \ref rpRefreshHint priority.
    void refresh(QCustomPlot::RefreshPriority refresh = QCustomPlot::rpQueuedRefresh);

signals:

protected:
   virtual void showEvent(QShowEvent *e);

private slots:
    

private:
  /**
   * @brief initPlotProperty
   */
  void initPlotProperty();

  /**
   * @brief clearDefaultRect creates an advanced axis, the default rectangular axis must be cleared
   */
  void clearDefaultRect();

  /**
   * @brief getRowCol row and column generation
   * @param row
   * @param col
   * @param ori
   */
  void getRowCol(int & amp;row, int & amp;col, Qt::Orientation ori);

  /**
   * @brief initAxis initializes the axis
   * @param xPAxis
   * @param yPAxis
   * @param strY
   * @param strX
   */
  void initAxis(QCPAxis *xPAxis, QCPAxis*yPAxis, const QString & amp;strY, const QString & amp;strX);

private:
  QCPMarginGroup *marginGroup;
  QVector<QCPAxisRect*> mVctRect;
  QHash<QCPAxisRect*, QList<QPair<bool, QCPGraph*> > > mHashRectGraphs;/*Rectangle----><Whether enabled, graphics pool>*/
};



#endif // MPLOT_H

#include "mplot.h"
#include <QMenu>
#include <QDebug>

MPlot::MPlot(QWidget *parent)
    : QCustomPlot(parent)
    , marginGroup(NULL)
{
    initPlotProperty();
     clearDefaultRect();
}

MPlot::~MPlot()
{
    qDebug() << __FUNCTION__;
}

void MPlot::setMInteractionType(MInteraction iType)
{
    QCP::Interactions interaction;
    switch (iType) {
    case mNone:
        interaction |= QCP::iNone;
        break;
    case mDefault: //Default mode: draggable, selectable, zoom (wheel zoom, right-click to zoom), right-click to cancel selection
        interaction |= QCP::iRangeZoom | QCP::iSelectPlottables | QCP::iRangeDrag;
        break;
    case mSelect: //Selection mode: non-dragable, selectable (supports multiple selections), right-click to pull the box to zoom, right-click to cancel the selection
        interaction |= QCP::iRangeZoom | QCP::iSelectPlottables | QCP::iMultiSelect;
        break;
    default:
        break;
    }
    this->setInteractions(interaction);
}

void MPlot::addAxisRect(const QString & amp;strY, const QString & amp;strX, const QString & amp;strTitile, \
                        int graphCnt, Qt::Orientation ori, MPlotTableType tableType)
{
     QCPAxisRect *rect = NULL;
     if(!rect)
     {
         rect = new QCPAxisRect(this);
         //Initialize title, initialize axis
         int row, col;
         getRowCol(row, col, ori);
         qDebug() << "row" << row << "col" << col;
         initAxis(rect->axis(QCPAxis::atLeft), rect->axis(QCPAxis::atBottom), strY, strX);
         //Create title
         QCPTextElement *title = new QCPTextElement(this);
         title->setText(strTitile);

         //layout
         QCPLayoutGrid *rectLayout = new QCPLayoutGrid;

         rectLayout->addElement(0,0,title);
         rectLayout->setRowSpacing(0);
         rectLayout->addElement(rectLayout->rowCount(), 0, rect);

         this->plotLayout()->addElement(row, col, rectLayout);
         this->plotLayout()->setRowSpacing(0);

         //Add elements to the layer
         foreach (QCPAxisRect *rect, this->axisRects())
         {
             foreach (QCPAxis *axis, rect->axes())
             {
                 axis->setLayer("axes");
                 axis->grid()->setLayer("grid");
             }
         }

         //Set the same blank
         rect->setMarginGroup(QCP::msLeft, marginGroup);

         this->plotLayout()->simplify();//remove blanks

         //Create 10 graphics by default
         for(int i = 0; i< graphCnt; + + i){
              addGraphsOnRect(rect, tableType);
         }
         //Set graphics to not enabled
         resetGraphsByRect(rect);
         mVctRect.append(rect);
     }
}

bool MPlot::addGraphsOnRect(QCPAxisRect *rect, MPlotTableType tableType)
{
    if(!rect) return false;
    switch (tableType) {
    case mGraph:
    {
        this->addGraph(rect->axis(QCPAxis::atBottom), rect->axis(QCPAxis::atLeft));
    }
        break;
    default:
        break;
    }

    return true;
}

void MPlot::resetGraphsByRect(QCPAxisRect* rect)
{
    QList<QPair<bool, QCPGraph*> > vctRectGraphs;
    foreach (auto item, rect->graphs())
    {
        vctRectGraphs.append(QPair<bool, QCPGraph*>(false, item));
    }
    mHashRectGraphs.insert(rect, vctRectGraphs);
}

int MPlot::rectCount() const
{
    return mVctRect.size();
}

QCPAxisRect *MPlot::axisRectByIndex(const int index)
{
    QCPAxisRect *rect = NULL;
    if(!rect & amp; & amp; index >= 0){
        rect = mVctRect.at(index);
    }
    return rect;
}

void MPlot::usingGraphs(int nRectIndex, QPair<int, int> & amp;item)
{
    if(mHashRectGraphs.isEmpty()) return;
    const auto & amp;items = mHashRectGraphs.value(axisRectByIndex(nRectIndex));
    int flag1 = 0, flag2 = 0;
    for(int i = 0; i < items.size(); + + i){
        if(items.at(i).first)
            flag1 + + ;
        else
            flag2 + + ;
    }
    item.first = flag1;
    item.second = flag2;
}

int MPlot::graphsCount(const int nRectIndex)
{
    if(mHashRectGraphs.isEmpty()) return -1;
    const auto & amp;items = mHashRectGraphs.value(axisRectByIndex(nRectIndex));
    return items.size();
}

QCPGraph *MPlot::getOneUnseGraph(int nRectIndex)
{
    if(mHashRectGraphs.isEmpty()) return NULL;
    QCPGraph *graph = NULL;
    if(!graph){
       auto & items = mHashRectGraphs[axisRectByIndex(nRectIndex)];
       for(int i = 0; i < items.size(); + + i){
           if(!items.at(i).first){
               auto &oneItem = items[i];
               graph = oneItem.second;
               oneItem.first = true;
               return graph;
           }
       }
    }
    return NULL;
}

void MPlot::clearData(const int nRectIndex)
{
    if(mHashRectGraphs.isEmpty()) return;
    auto & items = mHashRectGraphs[axisRectByIndex(nRectIndex)];
    for(int i = 0; i < items.size(); + + i)
    {
        auto &oneItem = items[i];
        QCPGraph *graph = oneItem.second;
        if(graph)
            graph->data().clear(); //Clear graph data
        oneItem.first = false; //Reset
    }
}

void MPlot::setData(int nRectIndex, QVector<int> vctIndex, QVector<double> vctKey, QVector<double> vctValue)
{
    Q_UNUSED(vctIndex)
    int count = qMin(vctKey.size(), vctValue.size());
    QVector<QCPGraphData> graphDatas;
    graphDatas.resize(count);
    for (int i=0; i< count; + + i)
    {
        graphDatas[i].key = vctKey[i];
        graphDatas[i].value = vctValue[i];
    }
    //Serial number to find rectangle-"Rectangle to find graphics-"Set data
    QCPGraph* oneGraph = NULL;
    oneGraph = getOneUnseGraph(nRectIndex);
    if(oneGraph){
        oneGraph->data()->add(graphDatas);
        oneGraph->rescaleAxes();
    }
    QPair<int, int> temp;
    usingGraphs(nRectIndex, temp);
    qWarning() << "axisrect index:" << nRectIndex << tr("using graph count:") <<temp.first << tr("not used graph count:") << temp.second;
}

void MPlot::refresh(QCustomPlot::RefreshPriority refresh)
{
    replot(refresh);
}

void MPlot::showEvent(QShowEvent *e)
{
    resize(this->sizeHint());
    QCustomPlot::showEvent(e);
}

void MPlot::initPlotProperty()
{
    QMargins margins(15,5,5,5);
    this->setContentsMargins(margins);
    //Interact with the chart: the default is zoom, drag and drop, graphics can be selected
    setMInteractionType(mDefault);
    marginGroup = new QCPMarginGroup(this);
}

void MPlot::clearDefaultRect()
{
    // Layout the advanced axis, first clear the default rectangular axis from the layout manager
    this->plotLayout()->clear();
}

void MPlot::getRowCol(int & amp;row, int & amp;col, Qt::Orientation ori)
{
    static int i = 0, j = 0;
    if(Qt::Horizontal == ori)
    {
        //Generate rows
       row = 0;
       col = i;
        + + i;
    }
    else if(Qt::Vertical == ori)
    {
       //Generate columns
        row = j;
        col = 0;
         + + j;
    }else
    {
    }
}

void MPlot::initAxis(QCPAxis *xPAxis, QCPAxis *yPAxis, const QString & amp; strY, const QString & amp;strX)
{
    if(xPAxis & amp; & yPAxis)
    {
        xPAxis->setLabel(strY);
        yPAxis->setLabel(strX);
        //Set the 0 tick mark
        xPAxis->grid()->setZeroLinePen(Qt::NoPen);
        yPAxis->grid()->setZeroLinePen(Qt::NoPen);
    }
}


The renderings are as follows: