QCustomPlot Discussion and Comments

Line as cursor on mouse over + values of all graphsReturn to overview

Hello guys,
in my customplot I have the possibility to add 10+ graphs.

What I want to do now, I want a line over the whole y-Axis on mouse over as a cursor and the values of every graph at the position of the cursor.
Somebody has an idea how to solve these two problems? I cant find any solution for this...

for the line, you would use QCPItemLine and on the mouse move signal, you would change the position of the line to be where you are on the y axis.

for the data, you would just loop through your graphs and find the value closest to that point on the x axis.

Thanks for the answer Ian.

After two months with QT I think I am still a newbie, even to QCustomPlot :D

Can you explain to me, how I set the position of the QCPItemLine?

And how to loop through my graph to find their values in the position of the QCPItemLine?

Ok, at the moment,I can show the QCPItemLine, but only when I press the plot (but I connected to the mouseMove-event.

Code at the moment:


connect(plot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(showCursor()));
....
void mainwindow::showCursor(QMouseEvent *event)
{
    double mouseX = plot->xAxis->pixelToCoord(event->pos().x());

    double start = plot->yAxis->pixelToCoord(0);
    double end = plot->yAxis->pixelToCoord(plot->size().height());

    cursor->start->setCoords(mouseX, start);
    cursor->end->setCoords(mouseX, end);
}

Found my mistake for the cursor, just had to add plot->replot(); at the end, now it works perfect.

Next topic, values of all graphs in the plot. I appreciate any help!

so an fyi about the previous topic is that you dont need to calculate start and end. if you set the line's y coordinate system to be based on axis rect, you can just use 0 and 1.

as for the values, just loop through your graphs using plot->graph(i). you can then use QCPGraph::findBegin and pass in the x coordinate to get the y value for that graph.

Thanks for the answer.

I tried this:

...
double mouseX = plot->xAxis->pixelToCoord(event->pos()->x());
...
for(int i=0; i<plot->graphCount(); ++i)
{
   double y = plot->graph(i)->findBegin(mouseX);
}

But I dont get the y-Value of the graph (currently testing with one graph only).
What am I doing wrong?

Erniberni: the findBegin you are using returns the index of the data point, not the y value. Clearly says so in the documentation:
QCPGraph::findBegin

Try this: graph(i)->data()->findBegin(mouseX)->value

(the data()->findBegin() returns an iterator)

I forgot that: The best method is still to use the selectTest, because it gives you the closest data point right away, and you don't need to convert pixels etc. With findBegin/findEnd you still have to decide with own code whether the left or right data point is actually closer to mouseX. selectTest does this for you.

DerManu's post at the bottom (31 october) mentions this in that thread:
http://www.qcustomplot.com/index.php/support/forum/183

Isso: I just noticed that before I saw your post, it was my fault, didnt have a look in the docu..


I didnt use the selectTest, but it still works perfect for me:

...
QCPItemLine *cursor = new QCPItemLine(plot);
...
connect(plot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(showVals(QMouseEvent*)));
...
void plotter::showVals(QMouseEvent *event)
{
    //for my "cursor"########
    double mouseX = plot->xAxis->pixelToCoord(event->pos().x());
    double startPos = plot->yAxis->pixelToCoord(0);
    double endPos = plot->yAxis->pixelToCoord(plot->size()->height());
    cursor->start->setCoords(mouseX, startPos);
    cursor->end->setCoords(mouseX, endPos);

    //for the  graph values #####
    for(int i=0; i<plot->graphCount(); ++i)
    {
        int index = plot->graph(i)->findBegin(mouseX);
        double x = plot->graph(i)->dataMainKey(index);
        double y = plot->graph(i)->dataMainValue(index);

        if(mouseX >= 0) 
        {
            qDebug() << index << "X:" << x << "Y:" << y;
        }
        else
        {
            qDebug() << index << "X:" << 0 << "Y:" << 0;
        }
    }    
}


I had a look at the selectTest, but couldnt figure out how to use it...

And last question:
You see the if(mouseX >= 0) ..i have this that it doesnt show my vals at index 0 when I am in x<0 with my mouse (--> x=0; y=0 for the graph(i).
Maybe it sounds stupid, but how do i get this for the right side/last index of my graph(i)?


Thank you for all your help!!

Ok, I got what I want now:

if(mouseX >= 0 && mouseX <= (plot->graph(i)->dataMainKey(plot->graph(i)->dataCount() - 1) + 1))
{
...
}

Hello,

I have been trying to do the very same thing and this post has been very helpful. I am very new to Qt so detailed explanations are very appreciated.

I have been trying to use QCustomPot::plottableClick to get data point values as opposed to only the mouse move signal as suggested by DerManu's (31 october) post in thread:
http://www.qcustomplot.com/index.php/support/forum/183

I followed the example in the interaction example project however in my project it does not seem to ever trigger the signal when I click on a graph. Has anyone had this problem? Can anyone give me an idea what might be happening?

Also an example in using would be helpful QCPGraph::selectTest.

Thank you.

I was able to figure out what was happening after all.

All I had to do was change the order I made the connections. Apparently connecting the mouseMove event after the plottableClick event disconects plottableClick

this does not work:


connect(ui->customPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,int,QMouseEvent*)), this, SLOT(findPoint(QCPAbstractPlottable*,int)));

connect(ui->customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(setPlotCursor(QMouseEvent*)));
// making this connection apparently disconnects the plottableClick connection. 


this works:

connect(ui->customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(setPlotCursor(QMouseEvent*)));

connect(ui->customPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,int,QMouseEvent*)), this, SLOT(findPoint(QCPAbstractPlottable*,int)));

Hello,
i have line2 (QCPItemLine *cursor = new QCPItemLine(m_ui->logplot);)
directly after my m_ui->setupUi(this);
but m_ui->logplot-> cursor->start->setCoords(mouseX, startPos);
m_ui->logplot-> cursor->end->setCoords(mouseX, endPos);
i get error for curser-> start "base operand of -> is not a pointer
same error if i write only cursor->start like in example below.

void MainWindow::showVals(QMouseEvent *event)
{
    //for my "cursor"########
    double mouseX = m_ui->logplot->xAxis->pixelToCoord(event->pos().x());
    double startPos = m_ui->logplot->yAxis->pixelToCoord(0);
    double endPos =m_ui->logplot->yAxis->pixelToCoord(100);
    cursor->start->setCoords(mouseX, startPos);
   cursor->end->setCoords(mouseX, endPos);

    //for the  graph values #####
    for(int i=0; i<m_ui->logplot->graphCount(); ++i)
    {
        int index = m_ui->logplot->graph(i)->findBegin(mouseX);
        double x = m_ui->logplot->graph(i)->dataMainKey(index);
        double y = m_ui->logplot->graph(i)->dataMainValue(index);

        if(mouseX >= 0 && mouseX <= (m_ui->logplot->graph(i)->dataMainKey(m_ui->logplot->graph(i)->dataCount() - 1) + 1))
        {
            qDebug() << index << "X:" << x << "Y:" << y;
        }
        else
        {
            qDebug() << index << "X:" << 0 << "Y:" << 0;
        }
    }
    m_ui->logplot->replot();
}