[gelöst] 'qwt zoomer' inkl. 'AxisAutoScale' möglich?

Alles rund um die Programmierung mit Qt
Antworten
topo
Beiträge: 24
Registriert: 3. Dezember 2009 16:58

[gelöst] 'qwt zoomer' inkl. 'AxisAutoScale' möglich?

Beitrag von topo »

Hallo Qt und Qwt Interessierte,

ich habe aktuell ein Problem mit meinem QwtPlot Widget. Ich habe QwtPlotCurves, die ich variabel hinzufügen und entfernen kann. Zur besseren Darstellung habe ich die Autoskalierung eingeschaltet und dies funktioniert auch sehr gut.

Leider habe ich nach hinzufügen des Qwt Zoomers diese super Funktion leider verloren, denn wenn ich hineinzoome wird natürlich eine andere Skalierung genommen, aber auch beim hinauszoomen wird nicht mehr in die ursprüngliche Auflösung gewechselt, sondern eine von der Zoomer Klasse festgelegt. Zudem funktioniert danach der ganze Autoscale nicht mehr :( .

:?: Nun meine Frage: Gibt es eine Möglichkeit beides zu Verbinden? Ich möchte die Autoskalierung nutzen, in eine Kurve hineinzoomen können und wenn ich wieder hinauszoome oder eine neue Kurve hinzufüge wieder in die Autoskalierung wechseln. Geht das? Wenn ja, wie?

Anbei mein aktueller Code aus der Initialisierung, der replot findet an anderer Stelle bei der Selektion einer anzuzeigenden Kurve als slot des signals currentIndexChanged der QComboBox statt:

Code: Alles auswählen


    m_pPlotWidget = new QwtPlot(m_pFrameBackground);
    m_pPlotWidget->setCanvasBackground( QColor(0,0,0) );

    QwtPlotGrid *grid = new QwtPlotGrid();
    grid->setPen( QPen(Qt::gray, 0.0, Qt::DotLine) );
    grid->enableX(true);
    grid->enableXMin(false);
    grid->enableY(true);
    grid->enableYMin(false);
    grid->attach(m_pPlotWidget);

    QFont axisFont("Arial", 10);
    m_pPlotWidget->setAxisFont(QwtPlot::yLeft, axisFont);
    m_pPlotWidget->setAxisFont(QwtPlot::xBottom, axisFont);

    // Enable axis auto scale
    m_pPlotWidget->setAxisAutoScale(QwtPlot::xBottom);
    m_pPlotWidget->setAxisAutoScale(QwtPlot::yLeft);

    m_pPlotWidget->plotLayout()->setAlignCanvasToScales(true);

    QwtPlotZoomer* zoomer = new CGuiPlotWidgetZoomer( m_pPlotWidget->canvas() );
#if QT_VERSION < 0x040000
    zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
        Qt::RightButton, Qt::ControlButton);
#else
    zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
        Qt::RightButton, Qt::ControlModifier);
#endif
    zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
        Qt::RightButton);

    QwtPlotPanner *panner = new QwtPlotPanner( m_pPlotWidget->canvas() );
    panner->setAxisEnabled(QwtPlot::yRight, false);
    panner->setMouseButton(Qt::MidButton);

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

Vielen Dank schon im Voraus für Eure Hilfe :D .

Viele Grüße,
topo
Zuletzt geändert von topo am 2. März 2010 17:58, insgesamt 1-mal geändert.
MiKla
Beiträge: 134
Registriert: 29. Juli 2007 15:29

Beitrag von MiKla »

Schau mal in den Examples nach. Da gibt es im Bode Example einen Toolbutton, mit dem das zoomen aktivieren kann. Dazu gibt es eine scrollzoomer Klasse (scrollzoomer.h, scrollzoomer, scrollbar.h, scrollbar.h). Diese habe ich direkt in mein Projekt übernommen.

Code: Alles auswählen

...
#include "scrollzoomer.h"
...
Zoomer *zoomer;
...

    zoomer = new Zoomer(qwtPlot->canvas());
    zoomer->setSelectionFlags(QwtPicker::DragSelection | QwtPicker::CornerToCorner);
    zoomer->setRubberBandPen(QPen(Qt::red, 2, Qt::DotLine));
    zoomer->setTrackerPen(QPen(Qt::red));
    zoomer->setTrackerMode(QwtPicker::AlwaysOn);
	zoomer->setHScrollBarPosition(ScrollZoomer::AttachedToScale);
    zoomer->setEnabled(false);
    zoomer->zoom(0);
...
    qwtPlot->replot();
    zoomer->setZoomBase();
...
void QScope::enableZoomMode(bool on)
{
//    panner->setEnabled(on);
    zoomer->setEnabled(on);
    zoomer->zoom(0);
    picker->setEnabled(!on);
    showInfo();
}
Vielleicht hilft Dir das weiter!!!

Michael
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Re: 'qwt zoomer' inkl. 'AxisAutoScale' möglich?

Beitrag von Uwe »

Leider habe ich nach hinzufügen des Qwt Zoomers diese super Funktion leider verloren, denn wenn ich hineinzoome wird natürlich eine andere Skalierung genommen, aber auch beim hinauszoomen wird nicht mehr in die ursprüngliche Auflösung gewechselt, sondern eine von der Zoomer Klasse festgelegt.
Der Zommer legt keine Auflösung fest, sondern wird mit der aktuellen Auflösung Deines Plots initialisiert. Wenn Du Autoskaling verwendest, mußt Du diese Initialisierung jeweils aktualisieren.
Zudem funktioniert danach der ganze Autoscale nicht mehr :( .
Sobald Du Skalierungen explizit zuweist ( hier durch zoomen ) wird Autoscaling abgeschaltet. D.h. Du musst es wieder anschalten, wenn Du herausgezoomt hast.

Ich würde Dir vorschlagen replot folgendermaßen zu überladen:

Code: Alles auswählen

void YourPlot::replot()
{
    QwtPlot::replot();

    if ( m_zoomer->zoomRectIndex() == 0 ) // not zoomed
    {
        for ( int axis = 0; axis < axisCnt; axis++ )
            setAxisAutoScale(axis, true);

        m_zoomer->setZoomBase(false); // reinitialize zoomer
    }
}
Habe es nicht selber ausprobiert - eventuell gibt es Reihenfolgeprobleme bei replots die vom Zoomer kommen. Aber so oder so ähnlich sollte es gehen.

Uwe
topo
Beiträge: 24
Registriert: 3. Dezember 2009 16:58

Beitrag von topo »

Danke für Eure guten Hinweise und Tipps. Das hilft mir beides auf alle Fälle weiter! Ich werde sie morgen ausprobieren und mich nochmal melden :D !

Viele Grüße,
Thomas
topo
Beiträge: 24
Registriert: 3. Dezember 2009 16:58

Beitrag von topo »

Hier das Fazit meiner heutigen Tests :wink: .

@Michael: Die "scrollzoomer.h" ist gut um sich einige Tipps zu holen, für das was ich machen will möchte ich aber nicht die ganze Klasse bei mir includieren, da ich nicht alles davon brauche. Trotzdem danke für den Hinweis :D .

@Uwe: Der Tipp war auch gut, aber im replot kann ich den Index nicht abfragen, da der Konstruktor des Zoomers wiederrum ein Replot auslöst und dadurch in der Replotfunktion auf einen uninitialisierten Pointer zugegriffen wird. Aber anhand des Beispiels habe ich eine Lösung gefunden:

Code: Alles auswählen

        // enable axis auto scale
        m_pPlotWidget->setAxisAutoScale(QwtPlot::xBottom);
        m_pPlotWidget->setAxisAutoScale(QwtPlot::yLeft);

        // replot
        m_pPlotWidget->replot();

        // get axis min and max values to calculate a rectangle for initialize the zoomer
        double xLowerBound = m_pPlotWidget->axisScaleDiv(QwtPlot::xBottom)->lowerBound();
        double xUpperBound = m_pPlotWidget->axisScaleDiv(QwtPlot::xBottom)->upperBound();
        double yLowerBound = m_pPlotWidget->axisScaleDiv(QwtPlot::yLeft)->lowerBound();
        double yUpperBound = m_pPlotWidget->axisScaleDiv(QwtPlot::yLeft)->upperBound();

        // initialize the zoomer with auto scale values
        m_pZoomer->setZoomBase( QwtDoubleRect(xLowerBound, yUpperBound, yUpperBound-yLowerBound, xUpperBound-xLowerBound) );
        // reset zoom level to 0
        m_pZoomer->setZoomBase(false);
Antworten