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

时间:2011-02-24 16:55:43

标签: c++ qt4 image-scaling

与google.com/maps类似,我希望如果我的鼠标位于QGraphicsItem上方,那么当我向前和向后移动wheelmouse时,鼠标下面的图像区域就是我的QGraphicsView的中心区域

我可以在我创建的自定义QGraphicsIte的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());

我可以添加什么来达到预期效果?

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

3 个答案:

答案 0 :(得分:1)

另见setTransformationAnchor( QGraphicsView::AnchorUnderMouse );

答案 1 :(得分:0)

让我们以更直接的方式重述您的目标。在轮子事件:

  1. 场景应放大/缩小
  2. 鼠标下的场景位置应保留在鼠标下
  3. 您已使用比例调用实现了(1)。剩下的是(2)。要将视图滚动到某个位置,您需要执行以下操作:

    horizontalScrollbar().setValue(x);
    verticalScrollbar().setValue(y);
    

    滚动场景,使(x,y)位于视图的左上角。但是你希望(x,y)位于鼠标位置(相对于QGraphicsView)。所以你需要滚动到(x-mx,y-my),其中(mx,my)是与QGraphicsView相关的鼠标位置,而(x,y)是在轮子事件之前鼠标下的场景位置。

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

答案 2 :(得分:0)

Th等式就像,,,

  

margin = -half_overflow +(((center_offset - click_offset)*   resize_ratio) - (center_offset - click_offset));

...你必须为x和y做。

下面的Ill粘贴在一些代码中,但要记住这个代码处理方形图像,所以我使用宽度来表示宽度和高度。 为了在矩形图像上使用它,你还需要抓住高度并在我有宽度的所有Y计算中使用它,以及设置我正在使用的所有变量如content_width等。但算法都在那里,你可以从代码中解决它......

        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>

CSS就像......

#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;
}