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

如何正确实现QGraphicsItemGroup网格吸附逻辑?现有实现存在偏移问题

自定义QGraphicsItemGroup网格吸附问题修复

问题现象

开发自定义QGraphicsItemGroup时,开启网格吸附(10像素步长)后,拖动组会以场景(0,0)为基准偏移。比如组初始在(100,100),拖动时会表现得像从(0,0)位置开始移动,无法保持拖动时鼠标与组的相对位置。

问题原因

当前代码直接使用鼠标的场景位置计算网格对齐坐标,忽略了鼠标在组内的点击偏移量——也就是按下鼠标时,鼠标点相对于组原点的距离。拖动时直接把组的原点设置为鼠标对齐后的位置,导致组的位置跳变,而非基于原拖动逻辑的偏移。

修复代码

from PyQt5.QtWidgets import QGraphicsItemGroup, QGraphicsSceneMouseEvent, QStyle
from PyQt5.QtGui import QColor, QPen
from PyQt5.QtCore import Qt

class CustomGraphicsItemGroup(QGraphicsItemGroup):
    def __init__(self, widget):
        super().__init__()
        self.widgets = widget
        self._mouse_offset = None  # 记录鼠标相对于组的偏移

    def paint(self, painter, option, widget=None):
        super().paint(painter, option, widget)
        if option.state & QStyle.State_Selected:
            pen = QPen(QColor('#e00202'), 2, cap=Qt.RoundCap)
            painter.setPen(pen)
            painter.drawRect(self.boundingRect())

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        # 记录按下鼠标时,鼠标相对于组原点的偏移(组坐标系下的位置)
        self._mouse_offset = event.pos()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
        if self.widgets.isChecked():
            block_size = 10
            # 1. 获取鼠标当前场景位置
            scene_pos = event.scenePos()
            # 2. 减去鼠标相对于组的偏移,得到组原点应该在的场景位置
            target_scene_pos = scene_pos - self._mouse_offset
            # 3. 对组原点的目标位置做网格对齐
            x = int(target_scene_pos.x() / block_size) * block_size
            y = int(target_scene_pos.y() / block_size) * block_size
            # 4. 设置组的位置
            self.setPos(x, y)
        else:
            super().mouseMoveEvent(event)

关键改动说明

  • 添加mousePressEvent:记录按下鼠标时,鼠标在组局部坐标系下的位置,这个偏移量在拖动过程中保持不变。
  • 修改mouseMoveEvent:用鼠标当前场景位置减去偏移量,得到组原点的目标场景位置,再对这个目标位置做网格对齐,确保拖动时鼠标与组的相对位置和按下时一致,不会出现跳变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:57:36