QCustomPlot Discussion and Comments

Replot only certain items using QCPLayersReturn to overview

I'm trying to figure out how to use QCPLayer to only replot certain items in the plot.

I am creating a custom qcustomplot by inheriting from QCustomPlot:

QCustomPlot_custom.h

#pragma once
#include "qcustomplot.h"    
#define USING_LAYER false

struct QCPCursor{
   QCPItemLine *hLine;
   QCPItemLine *vLine;
   QCPItemText* cursorText;
};

class QCustomPlot_custom :
   public QCustomPlot
{
   Q_OBJECT    
private slots:
   void mouseMove(QMouseEvent*);

public:
   QCustomPlot_custom(QWidget* parent = NULL);
   ~QCustomPlot_custom(){}
private:
   QCPLayer* cursorLayer;
   QCPCursor cursor;   
   void manageCursor(double x, double y, QPen pen);
public:
   void init(QVector<double> xdata, QVector<double> ydata);
};

This class initializes with some data to plot. It also overloads the mouseMove event to control a custom cursor. USING_LAYER set to true means that the custom cursor is added to it's own layer (cursorLayer).

By setting USING_LAYER to false I get the desired effect as seen here https://ibb.co/by4zpn:

The cursor is displayed by a horizontal and vertical line and the coordinates.

If I have many graphs in the plot and/or a lot of point in each graph, I will see a delay when moving the cursor. (Which is the reason I want to be able to replot only the cursor by setting it in a layer.)

QCustomPlot_custom.cpp

QCustomPlot_custom::QCustomPlot_custom(QWidget* parent)
{
   connect(this, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*)));   
   QCustomPlot::setInteraction(QCP::iRangeDrag, true);
   QCustomPlot::setInteraction(QCP::iRangeZoom, true);
   if (USING_LAYER){
      this->addLayer("cursorLayer", 0, QCustomPlot::limAbove);
      cursorLayer = new QCPLayer(this, "cursorLayer");
      cursorLayer->setMode(QCPLayer::lmBuffered);
   }
}

void QCustomPlot_custom::init(QVector<double> xdata, QVector<double> ydata)
{   
   this->addGraph();
   this->graph(0)->setData(xdata, ydata);

   QColor colorPen(10, 25, 180, 255);
   QPen pen;
   pen.setWidth(50);
   pen.setColor(colorPen);
   this->graph()->setLineStyle(QCPGraph::lsLine);
   this->graph()->setPen(QPen(colorPen));
   this->xAxis->setLabel("X-axis");
   this->yAxis->setLabel("Y-axis");      
   this->rescaleAxes();
   this->replot();
}

void QCustomPlot_custom::mouseMove(QMouseEvent* event)
{
   //Cursor coordinates:
   double x = this->xAxis->pixelToCoord(event->pos().x());
   double y = this->yAxis->pixelToCoord(event->pos().y());
   manageCursor(x, y, QPen(Qt::DashDotLine));            
   if (USING_LAYER)
      cursorLayer->replot(); 
   else
      this->replot();
}

void QCustomPlot_custom::manageCursor(double x, double y, QPen pen)
{
   if (cursor.hLine)
      this->removeItem(cursor.hLine);
   cursor.hLine = new QCPItemLine(this);   
   cursor.hLine->setPen(pen);
   cursor.hLine->start->setCoords(-QCPRange::maxRange, y);
   cursor.hLine->end->setCoords(QCPRange::maxRange, y);

   if (cursor.vLine)
      this->removeItem(cursor.vLine);
   cursor.vLine = new QCPItemLine(this);   
   cursor.vLine->setPen(pen);
   cursor.vLine->start->setCoords(x, -QCPRange::maxRange);
   cursor.vLine->end->setCoords(x, QCPRange::maxRange);

   //Coordinates as text:   
   if (cursor.cursorText)
      this->removeItem(cursor.cursorText);
   cursor.cursorText = new QCPItemText(this);
   cursor.cursorText->setText(QString("(%1, %2)").arg(x).arg(y));
   cursor.cursorText->position->setCoords(QPointF(x, y));
   QPointF pp = cursor.cursorText->position->pixelPosition() + QPointF(50.0, -15.0);
   cursor.cursorText->position->setPixelPosition(pp);
   cursor.cursorText->setFont(QFont(font().family(), 8));

   //Add to layer:
   if (USING_LAYER){
      cursor.hLine->setLayer(cursorLayer); 
      cursor.vLine->setLayer(cursorLayer); 
      cursor.cursorText->setLayer(cursorLayer);
   }
}

The function that initializes the class member:

void Qt_PlotTest::testPlot(){
   //Create some data and initalize plot:
   QVector<double> yData, xData;
   int imax = 100000;
   for (int i = 0; i < imax; i++){
      double x = double(i) / imax;
      xData.push_back(x);
      yData.push_back(pow(x, 2)*( 1.0 + 0.5*cos(20*x) + 0.1*sin(500*x - 0.1)));
   }
   ui.custom_QWidgetPlot->init(xData, yData);
}

When using the layer method, the cursor doesn't render. I tried understanding the documentation, but it is not clear for me how to correctly use QCPLayers.

How should I do this?

Solved my own problem.

The reason the above fails has to do with that I'm deleting and recreating the cursor before every replot.

So to make this work, I just initialized the cursor once (hline, vline, and cursorText). Then before the replot, I just apply the changes.