qwt plot - 如何根据鼠标光标进行缩放

时间:2018-04-29 15:43:40

标签: qt plot qwt

我在项目中使用了QWT。我用Qwtplotmagnifier进行缩放。 我想相对于鼠标光标放大。你能救我吗?

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,但找不到任何答案,所以这是我的。 根据这篇文章:Calculating view offset for zooming in at the position of the mouse cursor

为了实现GoogleMap样式的缩放,您必须继承QwtPlotMagnifier并重新实现widgetWheelEvent以便在发生滚动时存储光标位置,并使用rescale函数来更改行为缩放。

//widgetWheelEvent method
void CenterMouseMagnifier::widgetWheelEvent(QWheelEvent *wheelEvent)
{
   this->cursorPos = wheelEvent->pos();
   QwtPlotMagnifier::widgetWheelEvent(wheelEvent);
}

对于rescale方法,我使用了源代码并对其进行了修改。您需要使用画布的QwtScaleMap对象将鼠标光标坐标转换为绘图的轴坐标。最后,您只需要应用另一篇文章中给出的公式即可。

//rescale method
void CenterMouseMagnifier::rescale(double factor)
{
    QwtPlot* plt = plot();
    if ( plt == nullptr )
        return;

    factor = qAbs( factor );
    if ( factor == 1.0 || factor == 0.0 )
        return;

    bool doReplot = false;

    const bool autoReplot = plt->autoReplot();
    plt->setAutoReplot( false );

    for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
    {
        if ( isAxisEnabled( axisId ) )
        {
            const QwtScaleMap scaleMap = plt->canvasMap( axisId );

            double v1 = scaleMap.s1(); //v1 is the bottom value of the axis scale
            double v2 = scaleMap.s2(); //v2 is the top value of the axis scale

            if ( scaleMap.transformation() )
            {
                // the coordinate system of the paint device is always linear
                v1 = scaleMap.transform( v1 ); // scaleMap.p1()
                v2 = scaleMap.transform( v2 ); // scaleMap.p2()
            }

            double c=0; //represent the position of the cursor in the axis coordinates
            if (axisId == QwtPlot::xBottom) //we only work with these two axis
                c = scaleMap.invTransform(cursorPos.x());
            if (axisId == QwtPlot::yLeft)
                c = scaleMap.invTransform(cursorPos.y());

            const double center = 0.5 * ( v1 + v2 );
            const double width_2 = 0.5 * ( v2 - v1 ) * factor;
            const double newCenter = c - factor * (c - center);

            v1 = newCenter - width_2;
            v2 = newCenter + width_2;

            if ( scaleMap.transformation() )
            {
                v1 = scaleMap.invTransform( v1 );
                v2 = scaleMap.invTransform( v2 );
            }

            plt->setAxisScale( axisId, v1, v2 );
            doReplot = true;
        }
    }

    plt->setAutoReplot( autoReplot );

    if ( doReplot )
        plt->replot();
}

这对我来说很好。

答案 1 :(得分:0)

基于此forum post

bool ParentWidget::eventFilter(QObject *o, QEvent *e)
{
    QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
    if (mouseEvent->type()==QMouseEvent::MouseButtonPress && ((mouseEvent->buttons() & Qt::LeftButton)==Qt::LeftButton)) //do zoom on a mouse click
    {
        QRectF widgetRect(mouseEvent->pos().x() - 50, mouseEvent->pos().y() - 50, 100, 100); //build a rectangle around mouse cursor position

        const QwtScaleMap xMap = plot->canvasMap(zoom->xAxis());
        const QwtScaleMap yMap = plot->canvasMap(zoom->yAxis());
        QRectF scaleRect = QRectF(
            QPointF(xMap.invTransform(widgetRect.x()), yMap.invTransform(widgetRect.y())),
            QPointF(xMap.invTransform(widgetRect.right()), yMap.invTransform(widgetRect.bottom())) ); //translate mouse rectangle to zoom rectangle

        zoom->zoom(scaleRect);
    }
}