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

QGraphicsScene鼠标绘制矩形问题:起始点大于终点时矩形不显示

问题分析与修复方案

问题1:拖动绘制时start_point坐标大于end_point导致矩形不显示

原因

用QRectF(start_point, end_point)构造矩形时,若起点的x/y坐标大于终点,会生成宽高为负数的无效矩形,QGraphicsRectItem不会渲染这类矩形。

修复

构造矩形后调用normalized()方法,将矩形归一化为左上角到右下角的有效区域:

self.graphics_line.setRect(QtCore.QRectF(self.start_point, self.end_point).normalized())

问题2:右键唤出菜单时出现不可见矩形

原因

  1. mousePressEvent中右键判断逻辑错误:直接用QtCore.Qt.RightButton作为条件(非零值恒为真),导致只要self.graphics_line存在,左键点击也会进入右键分支,触发不必要操作;
  2. clean_scene方法未实现完整,无法正确清理旧矩形项,导致残留无效项;
  3. mouseReleaseEvent中按钮判断错误:使用event.buttons()(当前按住的按钮)而非event.button()(触发释放的按钮),逻辑不符合预期。

修复

  1. 修正右键判断条件,明确判断触发事件的是右键:
elif event.button() == QtCore.Qt.RightButton:
  1. 完善clean_scene方法,彻底清理场景中的矩形项:
def clean_scene(self):
    # 遍历并删除所有矩形项
    for item in list(self.items()):
        if isinstance(item, QtWidgets.QGraphicsRectItem):
            self.removeItem(item)
    self.graphics_line = None
  1. 修正mouseReleaseEvent的按钮判断逻辑:
if event.button() == QtCore.Qt.LeftButton:

修改后的完整代码

from PyQt5 import QtCore, QtWidgets, QtGui

class RectangleScene(QtWidgets.QGraphicsScene):
    def __init__(self, *args, **kwargs):
        super(RectangleScene, self).__init__(*args, **kwargs)
        self.graphics_line = None
        self.start_point = QtCore.QPointF()
        self.end_point = QtCore.QPointF()

    def clean_scene(self):
        # 清理所有矩形项
        for item in list(self.items()):
            if isinstance(item, QtWidgets.QGraphicsRectItem):
                self.removeItem(item)
        self.graphics_line = None

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.clean_scene()
            self.start_point = event.scenePos()
            self.end_point = self.start_point
            self.graphics_line = QtWidgets.QGraphicsRectItem(QtCore.QRectF(self.start_point, self.end_point))
            self.addItem(self.graphics_line)
            self.update_path()
        elif event.button() == QtCore.Qt.RightButton:
            # 交给父类处理上下文菜单
            super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self.end_point = event.scenePos()
            self.update_path()
            super(RectangleScene, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.end_point = event.scenePos()
            self.update_path()
            super(RectangleScene, self).mouseReleaseEvent(event)

    def update_path(self):
        if not self.start_point.isNull() and not self.end_point.isNull():
            # 归一化矩形,确保宽高为正
            rect = QtCore.QRectF(self.start_point, self.end_point).normalized()
            self.graphics_line.setRect(rect)
            self.graphics_line.setPen(QtGui.QPen(
                QtGui.QColor(242, 219, 7),
                3,
                QtCore.Qt.SolidLine,
                QtCore.Qt.FlatCap,
                QtCore.Qt.RoundJoin,
            ))

内容的提问来源于stack exchange,提问作者md.119

相关产品推荐
方舟 Agent Plan

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

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