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

如何在PyQt6中实现QGraphicsItem元素之间的防碰撞功能

以下是可直接运行的完整实现代码,支持单轴碰撞阻断,同时兼容QGraphicsEllipseItem和QGraphicsRectItem:

from PyQt6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem, QGraphicsItem
from PyQt6 import QtCore
import typing


class CollisionAvoidItem(QGraphicsEllipseItem):
    def __init__(self, geo):
        super().__init__(geo)
        self.setFlag(self.GraphicsItemFlag.ItemIsMovable)
        self.setFlag(self.GraphicsItemFlag.ItemSendsGeometryChanges)

    def itemChange(self, change: 'QGraphicsItem.GraphicsItemChange', value: typing.Any) -> typing.Any:
        if change == QGraphicsItem.GraphicsItemChange.ItemPositionChange:
            new_pos = value.toPointF()
            old_pos = self.pos()
            final_pos = QtCore.QPointF(new_pos)

            # 测试X方向移动是否碰撞
            self.setPos(final_pos.x(), old_pos.y())
            if self.collidingItems(QtCore.Qt.ItemSelectionMode.IntersectsShape):
                final_pos.setX(old_pos.x())

            # 测试Y方向移动是否碰撞
            self.setPos(final_pos.x(), final_pos.y())
            if self.collidingItems(QtCore.Qt.ItemSelectionMode.IntersectsShape):
                final_pos.setY(old_pos.y())

            # 还原测试前的位置,最终位置由返回值生效
            self.setPos(old_pos)
            return final_pos
        return super().itemChange(change, value)


if __name__ == "__main__":
    app = QApplication([])
    view = QGraphicsView()
    s = QGraphicsScene()
    s.addItem(CollisionAvoidItem(QtCore.QRectF(50, 50, 50, 50)))
    s.addItem(CollisionAvoidItem(QtCore.QRectF(200, 200, 50, 50)))
    # 可直接添加矩形元素测试,只需修改继承父类为QGraphicsRectItem即可
    # class RectItem(QGraphicsRectItem, CollisionAvoidItem): pass
    # s.addItem(RectItem(QtCore.QRectF(100, 100, 60, 40)))
    view.setScene(s)
    view.resize(600, 500)
    view.show()
    app.exec()

核心逻辑说明

  • 收到位置变更请求时,拆分X、Y两个轴分别做碰撞测试
  • 先仅修改X坐标测试是否碰撞,碰撞则保留原X坐标,否则使用新X坐标
  • 再基于处理后的X坐标,仅修改Y坐标测试是否碰撞,碰撞则保留原Y坐标,否则使用新Y坐标
  • 测试过程中临时修改的位置会回滚,最终通过返回值提交最终位置,避免影响Qt原生的事件流
  • 逻辑完全兼容所有QGraphicsItem子类,替换父类即可适配矩形、多边形等其他图形元素

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:48:04