Qwt provides its own Scaling Mechanism.
Qwtmagnifier class: abstract base class that provides the zoom-in and zoom-out feature. Inherited by qwtplotmagnifier. Shows the inheritance relationship:
Code Analysis:
I. qwtmagnifier class
1. constructor:
/*! Constructor \param parent Widget to be magnified*/QwtMagnifier::QwtMagnifier( QWidget *parent ): QObject( parent ){ d_data = new PrivateData(); setEnabled( true );}
The constructor requires passing in the scaled-out part parent.(Usually qwtplotcanvas ).
2. Install/uninstall event filters:
The qwtmagniier object's response to the "Mouse, scroll wheel, and keyboard" event is transmitted through the event mechanism. In the setenabled () function, you can enable or disable the zoom function by installing/uninstalling the Event Filter.
/*! \brief En/disable the magnifier When enabled is true an event filter is installed for the observed widget, otherwise the event filter is removed. \param on true or false \sa isEnabled(), eventFilter()*/void QwtMagnifier::setEnabled( bool on ){ if ( d_data->isEnabled != on ) { d_data->isEnabled = on; QObject *o = parent(); if ( o ) { if ( d_data->isEnabled ) o->installEventFilter( this ); else o->removeEventFilter( this ); } }}
This is an excellent example of using the QT event mechanism. Note the above Code: if enabled, install this (qwtmagnifier) Event Filter for the object O (that is, parent), that is, all events sent to object o are first transmitted to the eventfilter () function of qwtmagniier for filtering (processing ). To disable the zoom function, you only need to uninstall it.
3. Check the code of the Event Filter Function:
/*! \ Brief Event Filter when isenabled () the mouse events of the observed widget are filtered. \ Param object to be filtered \ Param event \ SA widgetmousepressevent (), alert (), widgetmousemoveevent (), widgetwheelevent (), alert () widgetkeyreleaseevent () */bool qwtmagniier:: eventfilter (qobject * object, qevent * event) {If (Object & object = parent ()) // identify the event owner object {Switch (Event-> type () {Case qevent: mousebuttonpress: {widgetmousepressevent (qmouseevent *) event); break;} case qevent:: mousemove: {widgetmousemoveevent (qmouseevent *) event); break;} case qevent: mousebuttonrelease: {widgetmousereleaseevent (qmouseevent *) event; break;} case qevent :: wheel: {widgetwheelevent (qwheelevent *) event); break;} case qevent: keypress: {widgetkeypressevent (qkeyevent *) event); break;} case qevent: keyrelease: {widgetkeyreleaseevent (qkeyevent *) event); break;} default :;}} return qobject: eventfilter (object, event );}
4. Let's look at the function to get the parent class object. We can learn a new method: bool qobject: inherits (const char * classname) const:
//! \return Parent widget, where the rescaling happensQWidget *QwtMagnifier::parentWidget(){ if ( parent()->inherits( "QWidget" ) ) return ( QWidget * )parent(); return NULL;}//! \return Parent widget, where the rescaling happensconst QWidget *QwtMagnifier::parentWidget() const{ if ( parent()->inherits( "QWidget" ) ) return ( const QWidget * )parent(); return NULL;}
Determines whether an object is an instance of the class named classname or its subclass instance. The Code is as follows:
inline bool inherits(const char *classname) const { return const_cast<QObject *>(this)->qt_metacast(classname) != 0; }
However, I have a question: why not use t qobject_cast (qobject * object )???
5. qwtmagniier is an abstract base class and has a function responsible for specific implementation of amplification and reduction:
protected: /*! Rescale the parent widget \param factor Scale factor */ virtual void rescale( double factor ) = 0;
The specific implementation of a pure virtual function is delayed in the subclass.
Ii. qwtplotmagniier class
First, let's take a look at the description of the qwtplotmagniier class in the qwt document:
Qwtplotmagnifier provides
Zooming, by magnifying in steps.
Using qwtplotmagnifier
Plot can be zoomed in/out in steps using keys, the mouse wheel or moving a mouse button in vertical direction.
Together with qwtplotzoomer and qwtplotpanner it
Is possible to implement individual and powerful navigation of the plot canvas.
-
See also:
-
Qwtplotzoomer, qwtplotpanner, qwtplot
Since most of the functions have been implemented in its basic class qwtmagniier, qwtplotmagniier only needs to re-implement the pure virtual function rescale (factor). Therefore, the qwtplotmagniier class code is relatively simple:
1. constructor:
/*! Constructor \param canvas Plot canvas to be magnified*/QwtPlotMagnifier::QwtPlotMagnifier( QwtPlotCanvas *canvas ): QwtMagnifier( canvas ){ d_data = new PrivateData();}
Note: The passed parameters are qwtplotcanvas rather than qwtplot.
2. You can only "set the specified axis" to be enlarged or reduced, while the other axes remain unchanged:
/*! \brief En/Disable an axis Only Axes that are enabled will be zoomed. All other axes will remain unchanged. \param axis Axis, see QwtPlot::Axis \param on On/Off \sa isAxisEnabled()*/void QwtPlotMagnifier::setAxisEnabled( int axis, bool on ){ if ( axis >= 0 && axis < QwtPlot::axisCnt ) d_data->isAxisEnabled[axis] = on;}
3. Return the canvas object qwtplotcanvas for the qwtplotmagniier class operation:
//! Return observed plot canvasQwtPlotCanvas *QwtPlotMagnifier::canvas(){ return qobject_cast<QwtPlotCanvas *>( parent() );}//! Return Observed plot canvasconst QwtPlotCanvas *QwtPlotMagnifier::canvas() const{ return qobject_cast<const QwtPlotCanvas *>( parent() );}
Used hereT qobject_cast (qobject * object ).
4. A good example of defensive encoding:
//! Return plot widget, containing the observed plot canvasQwtPlot *QwtPlotMagnifier::plot(){ QwtPlotCanvas *w = canvas(); if ( w ) return w->plot(); return NULL;}//! Return plot widget, containing the observed plot canvasconst QwtPlot *QwtPlotMagnifier::plot() const{ const QwtPlotCanvas *w = canvas(); if ( w ) return w->plot(); return NULL;}
I often write:
Return canvas ()-> plot ();
Coding is always fast, so I am anxious to see the effect and have no awareness of mistakes. How can we improve the code quality? Gap!
5. Finally, add the implementation code of the function rescale (factor:
/*! Zoom in/out the axes scales \param factor A value < 1.0 zooms in, a value > 1.0 zooms out.*/void QwtPlotMagnifier::rescale( double factor ){ factor = qAbs( factor ); if ( factor == 1.0 || factor == 0.0 ) return; bool doReplot = false; QwtPlot* plt = plot(); const bool autoReplot = plt->autoReplot(); plt->setAutoReplot( false ); for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { const QwtScaleDiv *scaleDiv = plt->axisScaleDiv( axisId ); if ( isAxisEnabled( axisId ) && scaleDiv->isValid() ) { const double center = scaleDiv->lowerBound() + scaleDiv->range() / 2; const double width_2 = scaleDiv->range() / 2 * factor; plt->setAxisScale( axisId, center - width_2, center + width_2 ); doReplot = true; } } plt->setAutoReplot( autoReplot ); if ( doReplot ) plt->replot();}
For more information about how to implement specific scaling classes, see.
Iii. Questions:
Currently, the role of the mouse, scroll wheel, and keyboard settings in the scaling operation class qwtmagniier is unclear.
void setMouseButton( int button, int buttonState = Qt::NoButton ); void setWheelButtonState( int buttonState ); void setZoomInKey( int key, int modifiers ); void setZoomOutKey( int key, int modifiers );
1. I tried many cases and did not see any results?
2. How can I restore an image to its original size with one click after I zoom in multiple times?