Hello there,
What I am trying to do is to limit further zoom out of the plot. I have found the event->delta() adding trick. The problem is that after i reach a certain number (for example -1000) i cannot zoom in anymore because the zooming is blocked. I cannot zoom out but also cant zoom in back. I was wondering either theres an event more specific than MouseWheel (ie. MouseWheelIn, MouseWheelOut)? Or maybe there is another way of acomplishing this.
The second thing I was wondering is either it is possible to create a zooming locks separate for each axis- for example, if i reach the zoom out limit of axis Y, then the zooming would continue only on axis X.
I Would really aprichiate any help in here, i really enjoy QCustomPlot.
Use the QCPAxis ::rangeChanged signal, of the axis you wish to limit.
You may manipulate/correct the range with setRange in a slot connected to this signal. This is useful if for example a maximum range span shall not be exceeded, or if the lower/upper range shouldn't go beyond certain values. For example, the following slot would limit the x axis to only positive ranges:
if (newRange.lower < 0) plot->xAxis->setRange(0, newRange.size());
setRange call with a completely fixed range, so create a temporary QCPRange fixedRange, initialize it with the given newRange, manipulate the bounds, and then pass it to a setRange call.
Could you only explain me how did you get newRange object?
The rangeChanged signal of QCPAxis provides it as parameter to you:
http://www.qcustomplot.com/documentation/classQCPAxis.html#a0894084e4c16a1736534c4095746f910
This thread will also be of interest to you:
http://www.qcustomplot.com/index.php/support/forum/486
Exacly what I needed, the code works now thank you!
I'm in the process of implementing convenience functions for QCPRange that make their bounding for such cases very easy. And while doing that I noticed (once again) that writing code that limits the ranges is slightly more tricky than it seems at first glance, if you want to do it right. So I thought I'd just post it here in case other people (or you) are interested.
The following code can be placed in a slot connected to QCPAxis ::rangeChanged , and will limit the axis range to lowerBound and upperBound.
double lowerBound = 0;
double upperBound = 10; // note: code assumes lowerBound < upperBound
QCPRange fixedRange(newRange);
if (fixedRange.lower < lowerBound)
{
fixedRange.lower = lowerBound;
fixedRange.upper = lowerBound + newRange.size();
if (fixedRange.upper > upperBound || qFuzzyCompare(newRange.size(), upperBound-lowerBound))
fixedRange.upper = upperBound;
mCustomPlot->xAxis->setRange(fixedRange); // adapt this line to use your plot/axis
} else if (fixedRange.upper > upperBound)
{
fixedRange.upper = upperBound;
fixedRange.lower = upperBound - newRange.size();
if (fixedRange.lower < lowerBound || qFuzzyCompare(newRange.size(), upperBound-lowerBound))
fixedRange.lower = lowerBound;
mCustomPlot->xAxis->setRange(fixedRange); // adapt this line to use your plot/axis
}
How do I know the plot pointer?
I have a number of plots > 1 all dynamically created.
Thus I can not write a connect code and a function for each plot. I need this to work automatically.
I solved this using the Qt property function and included your code.
Why is such functionality not within the QCP code itsself?
void MainWindow::setupPlot(QCustomPlot *plot, QString title)
{
...
connect(plot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange)));
connect(plot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange)));
}
void MainWindow::updatePlotData(QCustomPlot *plot, vector<double> & y0, vector<double> & y1 )
{
...
plot->replot();
plot->setProperty("xmin", plot->xAxis->range().minRange());
plot->setProperty("xmax", plot->xAxis->range().maxRange());
plot->setProperty("ymin", plot->yAxis->range().lower);
plot->setProperty("ymax", plot->yAxis->range().upper);
}
void MainWindow::xAxisChanged(const QCPRange & newRange)
{
QCPAxis * axis = qobject_cast<QCPAxis *>(QObject::sender());
QCustomPlot * plot = axis->parentPlot();
QCPRange limitRange(plot->property("xmin").toDouble(), plot->property("xmax").toDouble());
limitAxisRange(axis, newRange, limitRange);
}
void MainWindow::yAxisChanged(const QCPRange & newRange)
{
QCPAxis * axis = qobject_cast<QCPAxis *>(QObject::sender());
QCustomPlot * plot = axis->parentPlot();
QCPRange limitRange(plot->property("ymin").toDouble(), plot->property("ymax").toDouble());
limitAxisRange(axis, newRange, limitRange);
}
void MainWindow::limitAxisRange(QCPAxis * axis, const QCPRange & newRange, const QCPRange & limitRange)
{
auto lowerBound = limitRange.lower;
auto upperBound = limitRange.upper;
// code assumes upperBound > lowerBound
QCPRange fixedRange(newRange);
if (fixedRange.lower < lowerBound)
{
fixedRange.lower = lowerBound;
fixedRange.upper = lowerBound + newRange.size();
if (fixedRange.upper > upperBound || qFuzzyCompare(newRange.size(), upperBound-lowerBound))
fixedRange.upper = upperBound;
axis->setRange(fixedRange); // adapt this line to use your plot/axis
} else if (fixedRange.upper > upperBound)
{
fixedRange.upper = upperBound;
fixedRange.lower = upperBound - newRange.size();
if (fixedRange.lower < lowerBound || qFuzzyCompare(newRange.size(), upperBound-lowerBound))
fixedRange.lower = lowerBound;
axis->setRange(fixedRange); // adapt this line to use your plot/axis
}
}
Code like this is blinking
if (fixedRange.lower < lowerBound)
{
fixedRange.lower = lowerBound;
axis->setRange(fixedRange);