0

与 google.com/maps 类似,我希望这样,如果我的鼠标位于 QGraphicsItem 上,那么当我前后移动滚轮鼠标时,鼠标下方的图像区域就是我的 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());

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

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

4

3 回答 3

1

另见setTransformationAnchor( QGraphicsView::AnchorUnderMouse );

于 2013-07-15T14:01:57.743 回答
0

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

  1. 场景应该放大/缩小
  2. 鼠标下的场景位置应保持在鼠标下

您已经使用 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 的确切行为中),但数学概念是正确的,所以它应该足以让你让它工作。

于 2011-02-24T18:55:07.927 回答
0

这个方程就像 ,,,

边距 = -half_overflow + (((center_offset - click_offset) * resize_ratio) - (center_offset - click_offset));

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

下面我将粘贴一些代码,但请记住,此代码处理方形图像,因此我将宽度用于宽度和高度。为了让您在矩形图像上使用它,您还需要获取高度并在我有宽度的所有 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;
}
于 2014-08-29T18:32:07.130 回答