PDA

View Full Version : Sharing zoom with multiple plots



SeanM
7th February 2014, 17:14
I've got multiple plots that are aligned vertically, displaying data samples that share a common time scale. I've implemented a zoom feature using the mousewheel to zoom in/out based on current cursor position and that works great on the individual plot. What I'd like to do is sync all the plots together so that when a zoom happens on one plot, the others all zoom the same way, ensuring the plots all stay in sync.

Any thoughts on the best way to do that? Right now I maintain an internal zoom stack, so I could emit a signal that propagates that zoom stack out to the others. I'm not sure if that's the cleanest way to do it though?

Cah
9th February 2014, 00:19
I experimented with two plots...

I subclassed QwtPlotZoomer (see below)


class Zoomer : public QwtPlotZoomer
{
public:
Zoomer( QwtPlot* otherPlot, QWidget*w):QwtPlotZoomer(w), _otherPlot(otherPlot)
{

}
virtual void zoom( const QRectF & rc)
{
QwtPlotZoomer::zoom(rc);
QwtInterval intv = plot()->axisInterval (QwtPlot::xBottom);
_otherPlot->setAxisScale(QwtPlot::xBottom, intv.minValue(), intv.maxValue());
intv = plot()->axisInterval (QwtPlot::yLeft);
_otherPlot->setAxisScale(QwtPlot::yLeft, intv.minValue(), intv.maxValue());
_otherPlot->replot();
}
private:
QwtPlot* _otherPlot; //This could be list of plots
};

Now the custom zoomer is aware of _otherPlot whose scale is adjusted should any zooming occur.

Clients of custom plot do...

QwtPlot * plot = new QwtPlot(this);
QwtPlot * plot1 = new QwtPlot(this);

...
...

Zoomer* z = new Zoomer(plot1, plot->canvas());
Zoomer* z1 = new Zoomer(plot, plot1->canvas());

I did not check this thoroughly.

Added after 1 48 minutes:


Clients of custom plot do... Error...
This should read Clients of Zoomer do ...

Uwe
9th February 2014, 08:55
Maybe a more general approach would be to connect to the QwtScaleWidget::scaleDivChanged() signal.

Uwe

Cah
9th February 2014, 14:51
Maybe a more general approach would be to connect to the QwtScaleWidget::scaleDivChanged() signal.


Absolutely...


class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget * parent= NULL):QwtPlot(parent)
{

}
private slots:
void scaleDivChangedSlot ()
{
QwtPlot* plt = static_cast<QwtPlot*>((sender())->parent());
QwtInterval intv = plt->axisInterval (QwtPlot::xBottom);
this->setAxisScale(QwtPlot::xBottom, intv.minValue(), intv.maxValue());
intv = plt->axisInterval (QwtPlot::yLeft);
this->setAxisScale(QwtPlot::yLeft, intv.minValue(), intv.maxValue());
this->replot();
}
};



Plot* plot = new Plot;
Plot* plot1 = new Plot;

QObject::connect(((QObject*)plot->axisWidget(QwtPlot::xBottom)) , SIGNAL(scaleDivChanged () ), plot1, SLOT(scaleDivChangedSlot () ));
QObject::connect(((QObject*)plot1->axisWidget(QwtPlot::xBottom)) , SIGNAL(scaleDivChanged () ), plot, SLOT(scaleDivChangedSlot () ));


With this arrangement QwtPlotZoomer, QwtPlotMagnifier and QwtPlotPanner can operate and keep things in sync.