PDA

View Full Version : Zoomer for yLeft and yRight (Curves applied to both y-axis) does not work



pospiech
2nd May 2010, 15:36
Since the QwtPlotZoomer can not handle multiple y-Axis I have tried to implement a single Zoomer class handling both axis and thus two zoomer instances at once (I extended the class from one zoomer to a second).

However what happens is that the zoomed region is wrong. I susspect that the left zoomer is called first, and then the right zoomer on an already zoomed region (because I sometimes see a second rectangle and then a second zoom).

Here is a debug output:


--- Zoom Stack -----------------
0 *, QRectF(-10,3.72008e-44 19.98x1) , Y2: QRectF(-10,-0.172354 19.98x3.67272)

--- Zoom Stack -----------------
0 , QRectF(-10,3.72008e-44 19.98x1) , Y2: QRectF(-10,-0.172354 19.98x3.67272)

1 *, QRectF(-0.653651,3.72008e-44 1.23913x0.501961) , Y2: QRectF(-2.51714,-0.1
72354 4.97571x1.84356)

The actual zoom region was (X1Y1): (-2.5,0.5) - (2.5,0.0)

The code of the class is the following:


#include "Zoomer.h"

#include <qwt_plot.h>
#include <qwt_plot_panner.h>
#include <qwt_scale_widget.h>
#include <qwt_plot_layout.h>

#include <QDebug>

// TODO: add documentation

class PlotScale{
public:
PlotScale() : enabled(false){}
double min;
double max;
bool enabled;
};

class ZoomerPrivate{
public:
ZoomerPrivate(QwtPlot * qwtplot)
: zoomerY2(new QwtPlotZoomer(qwtplot->canvas()))
{
zoomerY2->setAxis(QwtPlot::xBottom, QwtPlot::yRight);
}
PlotScale plotScaleX;
PlotScale plotScaleY;
PlotScale plotScaleX2;
PlotScale plotScaleY2;

QScopedPointer<QwtPlotZoomer> zoomerY2;

};

Zoomer::Zoomer(QwtPlot * qwtplot)
: QwtPlotZoomer(qwtplot->canvas())
, plot(qwtplot)
, d(new ZoomerPrivate(qwtplot))
{
setAxis(QwtPlot::xBottom, QwtPlot::yLeft);
setTrackerMode(QwtPicker::AlwaysOn);
init();
connect(this, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(OnZoomed()));
}

Zoomer::~Zoomer()
{

}

void Zoomer::initScale()
{
d->zoomerY2->setZoomBase(true);
this->setZoomBase(true);
debugZoomerStack();
}

/*! \bug{setManualScaleX never used. Manual axis not applied} */
void Zoomer::setScaleX(double min, double max)
{
d->plotScaleX.min = min;
d->plotScaleX.max = max;
d->plotScaleX.enabled = true;
}

void Zoomer::setScaleY(double min, double max)
{
d->plotScaleY.min = min;
d->plotScaleY.max = max;
d->plotScaleY.enabled = true;
}

void Zoomer::init()
{
// LeftButton for the zooming
// MidButton for the panning
// RightButton: zoom out by 1
// Ctrl+RighButton: zoom out to full size

this->setMousePattern(QwtEventPattern::MouseSelect2,
Qt::RightButton, Qt::ControlModifier);
// d->zoomerY2->setMousePattern(QwtEventPattern::MouseSelect2,
// Qt::RightButton, Qt::ControlModifier);
// this->setMousePattern(QwtEventPattern::MouseSelect3,
// Qt::RightButton);

// Mid Mouse. Panner moves whole plot area
QwtPlotPanner *panner = new QwtPlotPanner(plot->canvas());
panner->setAxisEnabled(QwtPlot::yRight, plot->axisEnabled(QwtPlot::yRight));
panner->setMouseButton(Qt::MidButton);

// Avoid jumping when labels with more/less digits
// appear/disappear when scrolling vertically

const QFontMetrics fm(plot->axisWidget(QwtPlot::yLeft)->font());
QwtScaleDraw *sd = plot->axisScaleDraw(QwtPlot::yLeft);
sd->setMinimumExtent( fm.width("100.00") );

const QColor c(Qt::darkBlue);
this->setRubberBandPen(c);
this->setTrackerPen(c);

// Reinitialized the zoom stack with scaleRect() as base.
// Calls replot before initializing the zoomer with its scales.
initScale();
}

/*!
* modify the visual appearance of tracker text.
*/
QwtText Zoomer::trackerText( const QwtDoublePoint& p ) const
{
QwtText t( QwtPlotPicker::trackerText( p ));

QColor c(Qt::white);
c.setAlpha(180);
t.setBackgroundBrush( QBrush(c) );

return t;
}

/*!
* handle zoom events, especially reset zoom-base
* if back to initial zoom state
*/
void Zoomer::OnZoomed()
{
static int previousIndex = 0;

int index = this->zoomRectIndex();

debugZoomerStack();

// save startup scales
// TODO: can not retrieve scales. Must be set externally
if ((index == 0) && (previousIndex == 0)) {
d->plotScaleX.enabled = plot->axisAutoScale(xAxis());
d->plotScaleY.enabled = plot->axisAutoScale(yAxis());
initScale();
}

// only reset zoombase and replot if coming from
// zoomed state and state is at the initual size
if ((index == 0) && (previousIndex > 0)) {

if (!d->plotScaleX.enabled) {
plot->setAxisAutoScale(xAxis());
} else {
plot->setAxisScale(xAxis(), d->plotScaleX.min, d->plotScaleX.max);
}

if (!d->plotScaleY.enabled) {
plot->setAxisAutoScale(QwtPlot::yLeft);
plot->setAxisAutoScale(QwtPlot::yRight);
} else {
plot->setAxisScale(yAxis(), d->plotScaleY.min, d->plotScaleY.max);
}

initScale();
}
previousIndex = index;
}

void Zoomer::zoomOut()
{
this->zoom(-1);
d->zoomerY2->zoom(-1);
}

void Zoomer::zoomIn()
{
this->zoom(1);
d->zoomerY2->zoom(1);
}

void Zoomer::zoomBase()
{
this->zoom(0);
d->zoomerY2->zoom(0);
}


void Zoomer::debugZoomerStack()
{
int index = this->zoomRectIndex();
QStack<QwtDoubleRect> stack = this->zoomStack();
QStack<QwtDoubleRect> stackY2 = d->zoomerY2->zoomStack();
qDebug() << "--- Zoom Stack -----------------";
for(int i = 0; i < stack.size(); ++i) {
if (i == index) {
qDebug() << i << "*, " << stack.at(i) << ", Y2: " << stackY2.at(i);
} else {
qDebug() << i << ", " << stack.at(i) << ", Y2: " << stackY2.at(i);
}
}
}


Maybe my whole approach is wrong?
I do not know what really to debug.

Matthias

Uwe
2nd May 2010, 18:27
The bode example shows how to use 2 zoomers to zoom 2 y axes.

Uwe