如何求一个二次函数的center, radius, major axis, foci? 求例子说明

发布网友

我来回答

1个回答

热心网友

Qwt提供了自己的缩放机制。
QwtMagnifier类:提供逐步放大缩小功能的抽象基类。被QwtPlotMagnifier继承。继承关系如下图所示:

代码分析:
一、QwtMagnifier类
1、构造函数:

[cpp] view plain copy /*! Constructor \param parent Widget to be magnified */ QwtMagnifier::QwtMagnifier( QWidget *parent ): QObject( parent ) { d_data = new PrivateData(); setEnabled( true ); }

构造函数要求传入被放大缩小的部件parent (通常是QwtPlotCanvas)。
2、安装/卸载事件过滤器:
QwtMagnifier对象对“鼠标、滚轮,键盘”事件的响应(获取)是通过事件机制传递的。在setEnabled()函数中,通过安装/卸载事件过滤器来达到开启/禁用缩放功能的目的。

[cpp] view plain copy
/*!
\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 );
}
}
}
这是一个利用Qt事件机制的极好例子。 注意以上代码:如果开启,则为对象o(即parent)安装this(即QwtMagnifier)的事件过滤器,也就是说,所有发送到对象o的事件都会先传给QwtMagnifier的eventFilter()函数过滤(即处理)。如果要禁用缩放功能,则只需卸载即可。

3、看一下事件过滤器函数的代码:

[cpp] view plain copy
/*!
\brief Event filter

When isEnabled() the mouse events of the observed widget are filtered.

\param object Object to be filtered
\param event Event

\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent()
widgetKeyReleaseEvent()
*/
bool QwtMagnifier::eventFilter( QObject *object, QEvent *event )
{
if ( object && object == parent() ) // 判断事件属主对象
{
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、再看看获取父类对象的函数,可以学习一个新的方法: bool QObject::inherits ( const char * className ) const:

[cpp] view plain copy
//! \return Parent widget, where the rescaling happens
QWidget *QwtMagnifier::parentWidget()
{
if ( parent()->inherits( "QWidget" ) )
return ( QWidget * )parent();

return NULL;
}

//! \return Parent widget, where the rescaling happens
const QWidget *QwtMagnifier::parentWidget() const
{
if ( parent()->inherits( "QWidget" ) )
return ( const QWidget * )parent();

return NULL;
}
判断一个对象是否是名称为className 的类的实例或其子类实例。代码如下:

[cpp] view plain copy
inline bool inherits(const char *classname) const
{ return const_cast<QObject *>(this)->qt_metacast(classname) != 0; }
不过有一个疑问:这个地方为什么不使用 T qobject_cast ( QObject * object ) ???

5、QwtMagnifier是一个抽象基类,有一个负责具体实现放大缩小的功能函数:

[cpp] view plain copy
protected:
/*!
Rescale the parent widget
\param factor Scale factor
*/
virtual void rescale( double factor ) = 0;
纯虚函数,其具体实现被延迟到子类中。

二、QwtPlotMagnifier类

首先我们看看Qwt文档对QwtPlotMagnifier类的说明:

QwtPlotMagnifier provides zooming, by magnifying in steps.
Using QwtPlotMagnifier a 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 indivial and powerful navigation of the plot canvas.
See also:
QwtPlotZoomer, QwtPlotPanner, QwtPlot
由于大部分功能在其基类QwtMagnifier中已经实现,QwtPlotMagnifier只需要重新实现纯虚函数rescale( factor )即可,因此QwtPlotMagnifier类的代码也较为简单:
1、构造函数:

[cpp] view plain copy
/*!
Constructor
\param canvas Plot canvas to be magnified
*/
QwtPlotMagnifier::QwtPlotMagnifier( QwtPlotCanvas *canvas ):
QwtMagnifier( canvas )
{
d_data = new PrivateData();
}

注意:传递进去的参数是QwtPlotCanvas而非QwtPlot。
2、可以只“设置指定的轴”被放大或缩小,而其它轴保持不变:

[cpp] view plain copy
/*!
\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、返回QwtPlotMagnifier类操作的画布对象QwtPlotCanvas:

[cpp] view plain copy
//! Return observed plot canvas
QwtPlotCanvas *QwtPlotMagnifier::canvas()
{
return qobject_cast<QwtPlotCanvas *>( parent() );
}

//! Return Observed plot canvas
const QwtPlotCanvas *QwtPlotMagnifier::canvas() const
{
return qobject_cast<const QwtPlotCanvas *>( parent() );
}
这里使用了 T qobject_cast ( QObject * object ) 。

4、一个好的防御性编码实现例子:

[cpp] view plain copy
//! Return plot widget, containing the observed plot canvas
QwtPlot *QwtPlotMagnifier::plot()
{
QwtPlotCanvas *w = canvas();
if ( w )
return w->plot();

return NULL;
}

//! Return plot widget, containing the observed plot canvas
const QwtPlot *QwtPlotMagnifier::plot() const
{
const QwtPlotCanvas *w = canvas();
if ( w )
return w->plot();

return NULL;
}
我经常写成:

return canvas()->plot();
编码时总是求快,着急看到效果,没有防错意识。这样的编码习惯何谈提高代码质量? 差距啊!
5、最后,也贴上功能函数rescale( factor )的实现代码:

[cpp] view plain copy
/*!
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();
}
以后实现自己特定的缩放类时可以参考。

三、疑问:
现在对缩放操作类QwtMagnifier里的鼠标、滚轮、键盘的设置的作用不清楚。

[cpp] view plain copy
void setMouseButton( int button, int buttonState = Qt::NoButton );
void setWheelButtonState( int buttonState );
void setZoomInKey( int key, int modifiers );
void setZoomOutKey( int key, int modifiers );

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com