QCustomPlot Discussion and Comments

Create cursor #QcustomplotReturn to overview

Hello all :)

I would like to create a cursor that could indicate the points of a curve with the click of a mouse, and also to be able to move the cursor over the curve, even if it is possible to enter a value and the cursor goes to that value.

I looked a bit at the QCPItemLine library (QCustomPlot *parentPlot) but I don't know if this is the right direction.

For now I just have this piece of code to plot my graph:

    ui->plot->addGraph();
    ui->plot->graph(0)->setData(batch[i],batch1[i]);
    // give the axes some labels:
    ui->plot->xAxis->setLabel("batch 0");
    ui->plot->yAxis->setLabel("batch 1");
    // set axes ranges, so we see all data:
    ui->plot->xAxis->setRange(0, *std::max_element(batch[i].constBegin(), batch[i].constEnd())+1);
    ui->plot->yAxis->setRange(0, *std::max_element(batch1[i].constBegin(), batch1[etag].constEnd())+1);
    ui->plot->replot();
    ui->plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom );

if you have any advice or ideas, I'll take it!

good day to all :)

that's the way we do it. we have one horizontal and one vertical. we set it's coordinate system to plot coords and move it around whenever the mouse moves

Thanks ian :)

I'm going to explore this lib and do some tests but I must admit that an example would be cool to fully understand ahah

good day

You might also want to have a look at QCPItemTracer, which can track QCPGraph data (or be positioned freely)

thanks derManu
I'm gonna read this doc :)

In my Qcustomplot.cpp i have found this function :

void QCPItemTracer::setGraph(QCPGraph *graph)
{
  if (graph)
  {
    if (graph->parentPlot() == mParentPlot)
    {
      position->setType(QCPItemPosition::ptPlotCoords);
      position->setAxes(graph->keyAxis(), graph->valueAxis());
      mGraph = graph;
      updatePosition();
    } else
      qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
  } else
  {
    mGraph = 0;
  }
}

but how use this function with my code ? i don't understand realy good

Because my graph4 is a :

QCPGraph *QCustomPlot::graph(int index) const
{
  if (index >= 0 && index < mGraphs.size())
  {
    return mGraphs.at(index);
  } else
  {
    qDebug() << Q_FUNC_INFO << "index out of bounds:" << index;
    return 0;
  }
}

I try this with a example :

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////
////////////////                       Tracer TEST .cpp
////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


    // generate some data:
    QVector<double> x(101), y(101); // initialize with entries 0..100
    for (int i=0; i<101; ++i)
    {
      x[i] = i/50.0 - 1; // x goes from -1 to 1
      y[i] = x[i]*x[i]; // let's plot a quadratic function
    }
    // create graph and assign data to it:

    test_QCPGraph=ui->graph5->addGraph();
    ui->graph5->graph(0)->addData(x,y);

    tracer_test->setGraph(test_QCPGraph);


    // give the axes some labels:
    ui->graph5->xAxis->setLabel("x");
    ui->graph5->yAxis->setLabel("y");
    // set axes ranges, so we see all data:
    ui->graph5->xAxis->setRange(-1, 1);
    ui->graph5->yAxis->setRange(0, 1);

    ui->graph5->replot();

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////
////////////////                       Tracer TEST .h
////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

private :
QPointer<QCPGraph> test_QCPGraph;
QPointer<QCPItemTracer> tracer_test;

void QCPItemTracer::setGraph(QCPGraph *graph)
{
    qDebug() << "curseur";

  if (graph)
  {
      qDebug() << "curseur2";
    if (graph->parentPlot() == mParentPlot)
    {
        qDebug() << "curseur3";
      position->setType(QCPItemPosition::ptPlotCoords);
      position->setAxes(graph->keyAxis(), graph->valueAxis());
      mGraph = graph;
      updatePosition();
    } else
      qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item";
  } else
  {
      qDebug() << "curseur4";
    mGraph = 0;
  }
}

and in my debug i have this error :

16:04:37: Starting C:\build-version9-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\v12.exe ...
curseur
curseur2
16:04:40: Le programme s'est terminé subitement.
16:04:40: The process was ended forcefully.
16:04:40: C:\\build-version9-Desktop_Qt_5_9_9_MinGW_32bit-Debug\debug\v12.exe crashed.

where's the pangolin that makes me crash my code?

How do you initialize the variable tracer_test?

I'm an idiot. I forgot to initialize...

tracer_test=new QCPItemTracer(ui->graph5);

it doesn't get stuck in the setGraph function anymore.

it doesn't get stuck in the setGraph function anymore.

now I have to test the fct setInterploating to be able to go through my batch with a plotter, if i right :)

thanks isso

Okay checkpoint time

- have a tracer it's okay :
https://ibb.co/qjH5KYD

bool ok=true;

       tracer_test=new QCPItemTracer(ui->graph5);
    // generate some data:
       QVector<double> x(101), y(101); // initialize with entries 0..100
       double k=0.5;
       for (int i=0; i<101; ++i)
       {
         x[i] = i/50.0 - 1; // x goes from -1 to 1
         y[i] = x[i]*x[i]; // let's plot a quadratic function
       }
       // create graph and assign data to it:

       test_QCPGraph=ui->graph5->addGraph();
       test_QCPGraph->setData(x,y);
       test_QCPGraph->setPen(QPen(Qt::blue));
       test_QCPGraph->rescaleKeyAxis();

       //ui->graph5->addGraph();

       ui->graph5->graph(0)->addData(x,y);




       // give the axes some labels:
       ui->graph5->xAxis->setLabel("x");
       ui->graph5->yAxis->setLabel("y");
       // set axes ranges, so we see all data:
       ui->graph5->xAxis->setRange(-1, 1);
       ui->graph5->yAxis->setRange(0, 1);

       tracer_test->setGraph(test_QCPGraph);
       tracer_test->setGraphKey(k);
       tracer_test->setInterpolating(ok);
       tracer_test->setStyle(tracer_test->tsCircle);

       ui->graph5->replot();
       ui->graph5->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables );

but my objective and to be able to move this tracer with the mouse and to display its coordinates with text.

how to do it? that is a good question !

I don't know if anyone else will see this here, here's how I use it:
xx.h file:
//创建游标
QCPItemTracer *tracer0;
//图标标签
QCPItemText *textLabel0;
//游标标签
QCPItemText *tracerLabel0;
//游标要吸附哪个graph
QCPGraph *tracerGraph;
private slots:
void mouseMove0(QMouseEvent *e);
xx.c file:
//生成游标0
tracer0 = new QCPItemTracer(m_CustomPlot); //生成游标
tracer0->setInterpolating(false);
tracer0->setPen(QPen(Qt::red));//圆圈轮廓颜色
tracer0->setBrush(QBrush(Qt::red));//圆圈圈内颜色
tracer0->setStyle(QCPItemTracer::tsCrosshair);//圆圈
tracer0->setSize(5);//设置大小
//在图表上显示具体的IO点
textLabel0 = new QCPItemText(m_CustomPlot);//在QCustomplot中新建文字框
textLabel0->setPositionAlignment(Qt::AlignTop|Qt::AlignRight);//文字布局:顶、左对齐
textLabel0->position->setType(QCPItemPosition::ptAxisRectRatio);//位置类型(当前轴范围的比例为单位/实际坐标为单位)
textLabel0->position->setCoords(0.4, 0); //把文字框放在X轴的中间,Y轴的最顶部
//textLabel0->setText(QString("第%1组IO板 %2").arg(flag+1).arg(item->text()));
textLabel0->setPen(QPen(Qt::black)); //字体颜色
textLabel0->setPadding(QMargins(2,2,2,2));//文字距离边框几个像素
//游标内容1
tracerLabel0 = new QCPItemText(m_CustomPlot); //生成游标说明
tracerLabel0->setLayer("overlay");//设置图层为overlay,因为需要频繁刷新
tracerLabel0->setPen(QPen(Qt::red));//设置游标说明颜色
tracerLabel0->setPositionAlignment(Qt::AlignLeft | Qt::AlignTop);//左上
//下面这个语句很重要,它将游标说明锚固在tracer位置处,实现自动跟随
//将游标说明锚固在tracer位置处,实现自动跟随
tracerLabel0->position->setParentAnchor(tracer0->position);

connect(m_CustomPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove0(QMouseEvent*)));

mouseMove0 function:
void CustomPlotItem::mouseMove0(QMouseEvent *event)
{
if(m_CustomPlot->graphCount() > 0){
poszation = event->pos().x();
//获得鼠标位置处对应的横坐标数据x
double x0 = m_CustomPlot->xAxis->pixelToCoord(poszation);
//设置游标吸附于指定曲线
tracer0->setGraph(tracerGraph);
if(!tracerEnable){
tracer0->setGraph(NULL);
}
//将游标横坐标(key)设置成刚获得的横坐标数据x
tracer0->setGraphKey(x0);
//游标的纵坐标可以通过曲线数据线性插值自动获得
tracer0->setInterpolating(true);
//使得刚设置游标的横纵坐标位置生效
tracer0->updatePosition();

double xValue0 = ((int)(tracer0->position->key() *10))/10.0;//xValue就是游标的横坐标
//double yValue0 = intAarrayXCurrentPos[(int)(xValue0/g_sampleIntervalValue)];
//y轴值保留三位有效数字;
double yValue0 = (int)tracer0->position->value();

tracerLabel0->setText(QString("x = %1\ny = %2").arg(xValue0).arg(yValue0));//设置游标说明内容
m_CustomPlot->replot();//绘制器一定要重绘,否则看不到游标位置更新情况
}
}

My problem is that there are multiple graphs, and now they can only be attached to one graph each time, and cannot be attached to any graph. Tracer0->setGraph(xxx) is also modified here, but it doesn't work. Can anyone help me?

ReEdit: I don't know if anyone else will see this here, here's how I use it:

xx.h file:
//创建游标
QCPItemTracer *tracer0;
//图标标签
QCPItemText *textLabel0;
//游标标签
QCPItemText *tracerLabel0;
//游标要吸附哪个graph
QCPGraph *tracerGraph;
private slots:
void mouseMove0(QMouseEvent *e);

xx.c file:
//生成游标0
tracer0 = new QCPItemTracer(m_CustomPlot); //生成游标
tracer0->setInterpolating(false);
tracer0->setPen(QPen(Qt::red));//圆圈轮廓颜色
tracer0->setBrush(QBrush(Qt::red));//圆圈圈内颜色
tracer0->setStyle(QCPItemTracer::tsCrosshair);//圆圈
tracer0->setSize(5);//设置大小
//在图表上显示具体的IO点
textLabel0 = new QCPItemText(m_CustomPlot);//在QCustomplot中新建文字框
textLabel0->setPositionAlignment(Qt::AlignTop|Qt::AlignRight);//文字布局:顶、左对齐
textLabel0->position->setType(QCPItemPosition::ptAxisRectRatio);//位置类型(当前轴范围的比例为单位/实际坐标为单位)
textLabel0->position->setCoords(0.4, 0); //把文字框放在X轴的中间,Y轴的最顶部
//textLabel0->setText(QString("第%1组IO板 %2").arg(flag+1).arg(item->text()));
textLabel0->setPen(QPen(Qt::black)); //字体颜色
textLabel0->setPadding(QMargins(2,2,2,2));//文字距离边框几个像素
//游标内容1
tracerLabel0 = new QCPItemText(m_CustomPlot); //生成游标说明
tracerLabel0->setLayer("overlay");//设置图层为overlay,因为需要频繁刷新
tracerLabel0->setPen(QPen(Qt::red));//设置游标说明颜色
tracerLabel0->setPositionAlignment(Qt::AlignLeft | Qt::AlignTop);//左上
//下面这个语句很重要,它将游标说明锚固在tracer位置处,实现自动跟随
//将游标说明锚固在tracer位置处,实现自动跟随
tracerLabel0->position->setParentAnchor(tracer0->position);

connect(m_CustomPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove0(QMouseEvent*)));

mouseMove0 function:
void CustomPlotItem::mouseMove0(QMouseEvent *event)
{
if(m_CustomPlot->graphCount() > 0){
poszation = event->pos().x();
//获得鼠标位置处对应的横坐标数据x
double x0 = m_CustomPlot->xAxis->pixelToCoord(poszation);
//设置游标吸附于指定曲线
tracer0->setGraph(tracerGraph);
if(!tracerEnable){
tracer0->setGraph(NULL);
}
//将游标横坐标(key)设置成刚获得的横坐标数据x
tracer0->setGraphKey(x0);
//游标的纵坐标可以通过曲线数据线性插值自动获得
tracer0->setInterpolating(true);
//使得刚设置游标的横纵坐标位置生效
tracer0->updatePosition();

double xValue0 = ((int)(tracer0->position->key() *10))/10.0;//xValue就是游标的横坐标
//double yValue0 = intAarrayXCurrentPos[(int)(xValue0/g_sampleIntervalValue)];
//y轴值保留三位有效数字;
double yValue0 = (int)tracer0->position->value();

tracerLabel0->setText(QString("x = %1\ny = %2").arg(xValue0).arg(yValue0));//设置游标说明内容
m_CustomPlot->replot();//绘制器一定要重绘,否则看不到游标位置更新情况
}
}

My problem is that there are multiple graphs, and now they can only be attached to one graph each time, and cannot be attached to any graph. Tracer0->setGraph(xxx) is also modified here, but it doesn't work. Can anyone help me?