C++ 在Qt 4中直接在鼠标下方缩放图像

C++ 在Qt 4中直接在鼠标下方缩放图像,c++,qt4,image-scaling,C++,Qt4,Image Scaling,与google.com/maps类似,我希望这样,如果我的鼠标在QGraphicsSitem上,那么当我前后移动滚轮鼠标时,鼠标下的图像区域就是QGraphicsView的中心区域 我可以在我创建的自定义QGraphicsSite的wheelEvent方法中实现这一点吗 我有一些这样的代码 update(); qreal factor = 1.2; if (event->delta() < 0) factor = 1.0 / factor; scale(factor, facto

与google.com/maps类似,我希望这样,如果我的鼠标在QGraphicsSitem上,那么当我前后移动滚轮鼠标时,鼠标下的图像区域就是QGraphicsView的中心区域

我可以在我创建的自定义QGraphicsSite的wheelEvent方法中实现这一点吗

我有一些这样的代码

update();
qreal factor = 1.2;
if (event->delta() < 0)
  factor = 1.0 / factor;
scale(factor, factor);
scaleFactor *=factor;
this->scene()->setSceneRect(0,0,this->boundingRect().width(), this->boundingRect().height());
update();
qreal系数=1.2;
如果(事件->增量()<0)
系数=1.0/系数;
尺度(因子,因子);
scaleFactor*=因子;
this->scene()->setscen直立(0,0,this->boundingRect().width(),this->boundingRect().height());
我可以添加什么来达到预期效果


例如,在谷歌地图中,如果你将鼠标放在犹他州上方,并继续用滚轮鼠标放大,最终犹他州是视口中唯一剩下的东西。

让我们以更直接的方式重新表述你的目标。车轮事件:

  • 场景应该放大/缩小
  • 鼠标下的场景位置应保持在鼠标下
  • 您已经用scale调用实现了(1)。剩下的是(2)。要将视图滚动到特定位置,需要执行以下操作:

    horizontalScrollbar().setValue(x);
    verticalScrollbar().setValue(y);
    
    这将滚动场景,使(x,y)位于视图的左上角。但是您希望(x,y)位于鼠标位置(相对于QGraphicsView)。因此,您需要滚动到(x-mx,y-my),其中(mx,my)是相对于QGraphicsView的鼠标位置,(x,y)是滚轮事件之前鼠标下方的场景位置


    这是未经测试的,在细节上可能是错误的(例如在QScrollBar::setValue的确切行为中),但数学概念是正确的,因此它应该足以让它工作。

    另请参见
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse)


    这个方程就像

    边距=-half_overflow+((中心偏移-单击偏移)* 调整_比率)-(中心_偏移-单击_偏移))

    。。。你必须为x和y做这件事

    下面我将粘贴一些代码来实现这一点,但请记住,这段代码处理的是方形图像,所以我使用宽度表示宽度和高度。 要在矩形图像上使用它,您还需要获取高度,并在所有Y计算中使用它,其中我有宽度,以及设置我使用的所有变量,如内容宽度等。但是算法都在那里,您可以从代码中计算出来

            zoomChart: function(e)
            {
                    var chart_max = 2048;
                    var zoom_max = egapp.user.options.zoom_multiplier || 2; // >= 2
                    var chart_bounds = $('#egapp_chart_bounds');
                    var chart_imgs = chart_bounds.find('img');
                    var width = chart_imgs.width();
                    if (width == chart_bounds.width()) { // zoom in
                            // margin = -half_overflow + (((center_offset - click_offset) * resize_ratio) - (center_offset - click_offset));
                            chart_bounds.removeClass('egapp_zoom_in');
                            if (width == chart_max)
                                    return;
                            chart_bounds.addClass('egapp_zoom_out');
                            var new_width = parseInt(width * zoom_max);
                            if (new_width > chart_max)
                                    new_width = chart_max;
                            var ratio = new_width / width;
                            var moveX = moveY = -((new_width - width) / 2);
                            var chart_offset = chart_bounds.offset();
                            var offsetX = (chart_offset.left + (width / 2)) - e.pageX;
                            var offsetY = (chart_offset.top + (width / 2)) - e.pageY;
                            moveX += parseInt((offsetX * ratio) - offsetX);
                            moveY += parseInt((offsetY * ratio) - offsetY);
                            chart_imgs.animate({width: new_width+'px', height: new_width+'px', marginLeft: moveX+'px', marginTop: moveY+'px'}, 'fast');
                            chart_bounds.addClass('egapp_zoom_out');
                    }
                    else { // zoom out
                            var new_width = egapp.content_width - 10;
                            chart_imgs.animate({width: new_width+'px', height: new_width+'px', marginLeft: 0, marginTop: 0}, 'fast');
                            chart_bounds.removeClass('egapp_zoom_out').addClass('egapp_zoom_in');
                    }
            },
    
    HTML有点像

    <div id="egapp_chart_bounds" style="width: 608px; height: 608px;" class="egapp_zoom_in">
        <img id="egapp_timeline_chart" src="some.image" class="egapp_chart" style="width: 608px; height: 608px; margin-left: 0px; margin-top: 0px;">
        <img id="egapp_expression_chart_9" src="overlay.image" class="egapp_chart_overlay" style="width: 608px; height: 608px;">
    </div>
    

    我可以在QGraphicsItem的控制盘事件中执行此操作吗?该项目是什么有wheelEvent在它,而不是QGraphicsViewAh,我想你的wheelEvent是在QGV。如果是在QGI中,您应该仍然能够做到这一点。唯一的区别在于确定
    (x,y)
    (使用qgraphicsceneouseevent::screenPos)和
    (mx,my)
    (使用qgraphicsceneouseevent::scenePos)的方式。无论如何,我认为在QGV中实现wheelEvent比在QGI中实现wheelEvent更干净。
    #egapp_chart_bounds{
            overflow: hidden;
    }
    .egapp_chart, .egapp_chart_overlay{
            position: absolute;
    }
    
    .egapp_zoom_in{
            cursor: -moz-zoom-in;
            cursor: -webkit-zoom-in;
            cursor: zoom-in;
    }
    .egapp_zoom_out{
            cursor: -moz-zoom-out;
            cursor: -webkit-zoom-out;
            cursor: zoom-out;
    }