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: