程序化滚动QGraphicsView

4 投票
4 回答
5231 浏览
提问于 2025-04-15 12:47

我想在我的(Py)Qt 应用程序中的 QGraphicsView 上实现一个滚动/平移的功能。这个功能应该是这样的:用户按下中间鼠标键,然后在移动鼠标时,视图会跟着滚动(这个功能其实很常见)。
我尝试使用 QWidget 继承来的 scroll() 方法。但是,这个方法似乎是移动了整个视图,包括滚动条。请看图片。
所以,既然这不是我应该使用的方法,那我该怎么做呢?或者说这其实是正确的方法,但我做错了什么?我使用的代码是:

   def __init__(self):
       ...

       self.ui.imageArea.mousePressEvent=self.evImagePress
       self.ui.imageArea.mouseMoveEvent=self.evMouseMove

       self.scrollOnMove=False
       self.scrollOrigin=[]

       ...

   def evImagePress(self, event):
        if event.button() == Qt.LeftButton:
            self.evImageLeftClick(event)
        if event.button() == Qt.MidButton:
            self.scrollOnMove=not self.scrollOnMove
            if self.scrollOnMove:
                self.scrollOrigin=[event.x(), event.y()]
   ...

   def evMouseMove(self, event):
        if self.scrollOnMove:
            self.ui.imageArea.scroll(event.x()-self.scrollOrigin[0],
                                     event.y()-self.scrollOrigin[1])

它的表现和我预期的一样,除了整个移动小部件的事情。

滚动失败 http://img55.imageshack.us/img55/3222/scrollfail.jpg

4 个回答

1

denis给出的答案是正确的,可以让翻译功能正常工作。PF4Public的评论也很有道理:这可能会影响缩放。我的解决办法和PF4Public的不一样——我不是使用mapToScene,而是保留锚点,然后在翻译后再恢复它:

previousAnchor = view.transformationAnchor()
#have to set this for self.translate() to work.
view.setTransformationAnchor(QGraphicsView.NoAnchor)
view.translate(x_diff,y_diff)
#have to reset the anchor or scaling (zoom) stops working:
view.setTransformationAnchor(previousAnchor)
4

我对translate()方法的补充说明。这个方法很好用,除非你对场景进行了缩放。如果你缩放了场景,你会发现图像和鼠标的移动不同步。这时候,mapToScene()就派上用场了。你需要把鼠标事件中的点转换成场景坐标。然后,把转换后的差值传给translate(),这样一来,你的场景就能非常精准地跟随鼠标移动了。

举个例子:

QPointF tmp2 = mapToScene(event->pos());
QPointF tmp = tmp2.mapToScene(previous_point);
translate(tmp.x(),tmp.y());
3

我自己没有做过这个,但这是来自于QGraphicsView的文档内容。

... 当场景的大小超过滚动条的范围时,你可以选择使用translate()来浏览场景。

使用scroll是在移动这个小部件,而translate可以帮助你实现想要的效果,就是在视图下移动QGraphicsScene的内容。

撰写回答