QCustomPlot Discussion and Comments

Disable negative axis in dragging and zoomingReturn to overview

Hi

I am trying to set the graph so that when users zoom in or drag the graph they will never see the negative x-axis. Here is my connect statement:

connect(ui->graph_1, SIGNAL(beforeReplot()),this,SLOT(PlotRangeChanged()));

And here is the custom slot:

void myapp::PlotRangeChanged()
{
    if(ui->graph_1->xAxis->range().lower <= 0)
    {
       ui->graph_1->xAxis->setRangeLower(0);
    }
    if(ui->graph_1->xAxis->range().upper <= 1)
    {
        ui->graph_1->xAxis->setRangeUpper(1);
    }
}

My problem is, it works in some ways but not all. I mean, if I drag the graph to the right(toward to positive infinite) slowly, the x-axis will not show the negative value. However, when I drag it in a fast way or holding the left button pressed and keep dragging I will still see the negative part. Once I press the mouse again the checking works again. Any idea about how to avoid "over dragging"?

(Sorry for bad description)

Hi Evan,

you can use the rangeChanged(QCPRange) singal of your x-axis instead of beforeReplot() to restrict the x-range to be only positive. Try something like this:

connect(ui->graph_1->xAxis,    SIGNAL(rangeChanged(QCPRange)), this,   SLOT(onXRangeChanged(QCPRange)));

void myapp::onXRangeChanged(const QCPRange &range)
{
    QCPRange boundedRange = range;
    double lowerRangeBound = 0;

    if(boundedRange.lower < lowerRangeBound) {  // restrict max zoom in
        boundedRange.lower = lowerRangeBound;
        boundedRange.upper = lowerRangeBound + boundedRange.size();
   }

    ui->graph_1->xAxis->setRange(boundedRange);
}

~ Markus

Hi Markus,

Thanks for reply. But the code still doesn't work in some corner cases. To re-produce the bug one way is just keep dragging the graph on the positive direction then the negative part will sometimes show up for a short time. It seems like the "long dragging" intersection sometimes won't trigger the rangeChanged signal. Also when trying to "lock" the zero index on the very left of the graph, the dragging action actually works similar to zooming. Therefore I am not sure if any conflicts actually occur.

Evan

Hi Evan,

There's a little bug in your code.
Say you move the range very fast, so the new range is (-3, -2). Your code then checks the lower bound, finds that it's below 0 and sets it to 0. So the range that it tries to set is (0, -2)... oops. That's an invalid range, so internally, QCustomPlot flips it around to be valid again: (-2, 0). Now your second check detects that the upper range is <= 1 and sets it to 1: (-2, 1). And this is how you get negative ranges with your current code.

To fix this, you could add another check inside the lower<=0 branch, which checks for upper<=1:

  if (plot->xAxis->range().lower <= 0)
  {
    if (plot->xAxis->range().upper <= 1) // added this
      plot->xAxis->setRangeUpper(1);     // added this
    plot->xAxis->setRangeLower(0);
  } else if (plot->xAxis->range().upper <= 1)
  {
    plot->xAxis->setRangeUpper(1);
  }

This fixed code works both as a slot reacting to beforeReplot or rangeChanged.

I met the same problem.There is my code below,it seems work well.I set lower bound to 0 and upper bound to 1,

void MainWindow::yAxisRangeChanged( const QCPRange &newRange, const QCPRange &oldRange )
{
    if(newRange.lower<=0 || newRange.lower>=1)
    {
        m_pPlot1->yAxis->setRangeLower(0);
    }
    if(newRange.upper<0 || newRange.upper>=1)
    {
        m_pPlot1->yAxis->setRangeUpper(1);
    }
}


Hi Simon,

Your code has the same bug as EvanChan's initial code. Please read my previous post to resolve it.

Hi DerManu,
Thank you for your reply.I'm sorry to not expressed clearly.I have resolved the problem by the code I posted.
It's looks not smart but really worked.
Thanks for your excellent work again,you help me a lot.