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

如何实现点击QGraphicsView/QGraphicsScene画布可绘制且可拖动的QGraphicsRectItem

解决QGraphicsView点击生成矩形+自由拖动问题

问题原因

你的代码存在两个核心问题:

  • 重写GraphicsView.mousePressEvent时完全覆盖了父类逻辑,没有调用super().mousePressEvent(event),导致QGraphicsScene无法将鼠标事件传递给已存在的矩形项,只有当点击位置恰好落在矩形的pen线条上时,才会触发item的鼠标事件,所以拖动异常困难。
  • 每次点击都会无条件生成新矩形,就算点击的是已有的矩形,也会在上面叠加新的,干扰正常拖动操作。

解决方案

修改GraphicsView的mousePressEvent逻辑:先判断点击位置是否存在可交互的图形项,不存在时再生成新矩形;同时必须调用父类的鼠标事件处理方法,让场景中的item能正常接收鼠标事件。

修改后的完整代码

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QMouseEvent, QPen
from PyQt5.QtWidgets import (
    QApplication,
    QGraphicsItem,
    QGraphicsRectItem,
    QGraphicsScene,
    QGraphicsView,
)


class RectangleItem(QGraphicsRectItem):
    def __init__(self, x: float, y: float, width: float, height: float):
        super().__init__(x, y, width, height)

        self.setBrush(QBrush(Qt.red))
        self.setPen(QPen(Qt.black, 20))

        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)


class GraphicsView(QGraphicsView):
    def __init__(self, scene: QGraphicsScene):
        super().__init__(scene)

    def mousePressEvent(self, event: QMouseEvent):
        scene_position = self.mapToScene(event.pos())
        # 获取点击位置的所有图形项,过滤出可移动的项
        clicked_items = [item for item in self.scene().items(scene_position) 
                        if item.flags() & QGraphicsItem.ItemIsMovable]
        
        if not clicked_items:
            # 未点击到可移动item时,生成新矩形
            rectangle = RectangleItem(scene_position.x(), scene_position.y(), 100, 100)
            self.scene().addItem(rectangle)
        
        # 调用父类方法,让场景处理item的鼠标事件
        super().mousePressEvent(event)


app = QApplication([])
scene = QGraphicsScene()
view = GraphicsView(scene)
view.show()
app.exec()

关键说明

  • self.scene().items(scene_position)会返回点击位置的所有图形项,我们通过过滤ItemIsMovable标记,判断是否点击到了已有的可拖动矩形。
  • 只有在未点击到可拖动item时才生成新矩形,避免叠加干扰。
  • super().mousePressEvent(event)是核心:它会让QGraphicsView把鼠标事件传递给场景,再由场景分发给对应的item,这样矩形就能响应任意位置的点击拖动了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:25:10