You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将QGraphicsView定位到鼠标双击位置?已试centerOn/translate无效

解决QGraphicsView双击后无法定位到鼠标位置的问题

我看了你的代码,发现问题主要出在场景范围过小以及视图默认缩放行为的影响上,导致centerOn的效果看起来不明显甚至没生效。下面给你一步步分析和修复:

问题根源拆解

  • 场景空间不足:你只添加了一个100x100的椭圆,场景的boundingRect被限制在这个椭圆的范围内。QGraphicsView默认会自动缩放视图以适配整个场景,所以初始时椭圆会被放大填满600x600的窗口。此时双击视图任意位置,转换后的场景坐标都落在椭圆范围内,而视图已经把这个范围居中显示了,所以调用centerOn看起来没有变化。
  • 缺少可滚动的场景区域:要让centerOn的滚动效果直观体现,场景需要有足够大的范围,允许视图滚动到不同位置。

修复后的完整代码

我调整了代码的关键部分,确保双击定位功能正常工作:

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys

class SurfViewer(QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.setFixedWidth(600)
        self.setFixedHeight(600)
        photo = PhotoViewer()
        self.setCentralWidget(photo)

class PhotoViewer(QGraphicsView):
    def __init__(self, parent=None):
        super(PhotoViewer, self).__init__(parent)
        self.parent = parent
        self.scene = QGraphicsScene(self)
        # 设置足够大的场景范围,提供滚动空间
        self.scene.setSceneRect(-500, -500, 1000, 1000)
        self.setScene(self.scene)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setFrameShape(QFrame.NoFrame)
        
        # 添加背景矩形,方便直观看到场景范围
        bg_item = QGraphicsRectItem(-500, -500, 1000, 1000)
        bg_item.setBrush(QBrush(Qt.lightGray, style=Qt.SolidPattern))
        self.scene.addItem(bg_item)
        
        self.UpdateScene()

    def mouseDoubleClickEvent(self, event):
        # 获取视图坐标并转换为场景坐标
        view_pos = event.pos()
        scene_pos = self.mapToScene(view_pos)
        print(f"双击的场景坐标: {scene_pos.x()}, {scene_pos.y()}")
        
        # 将该场景坐标设为视图中心
        self.centerOn(scene_pos)
        # 无需手动调用update,centerOn会自动触发视图更新

    def UpdateScene(self):
        xsize=100
        ysize=100
        newitem = QGraphicsEllipseItem(0-xsize/2., 0-ysize/2., xsize, ysize)
        newitem.setBrush(QBrush(Qt.black, style = Qt.SolidPattern))
        self.scene.addItem(newitem)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.setWindowTitle('window')
    ex.show()
    sys.exit(app.exec_())

关键修改说明

  • 扩大场景范围:通过self.scene.setSceneRect(-500, -500, 1000, 1000)定义了一个1000x1000的场景,让视图有足够空间滚动。
  • 添加背景参考:新增的浅灰色背景矩形能让你直观看到场景边界,测试时可以清晰观察到视图中心的变化。
  • 简化事件处理:移除了不必要的update()调用,因为centerOn会自动触发视图的重绘和滚动逻辑。

现在运行修改后的代码,双击视图任意位置,视图就会自动滚动,将你双击的位置设为视图中心了。

内容的提问来源于stack exchange,提问作者ymmx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:03:00