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:右键唤出菜单时出现不可见矩形
原因
mousePressEvent中右键判断逻辑错误:直接用QtCore.Qt.RightButton作为条件(非零值恒为真),导致只要self.graphics_line存在,左键点击也会进入右键分支,触发不必要操作;clean_scene方法未实现完整,无法正确清理旧矩形项,导致残留无效项;mouseReleaseEvent中按钮判断错误:使用event.buttons()(当前按住的按钮)而非event.button()(触发释放的按钮),逻辑不符合预期。
修复
- 修正右键判断条件,明确判断触发事件的是右键:
elif event.button() == QtCore.Qt.RightButton:
- 完善
clean_scene方法,彻底清理场景中的矩形项:
def clean_scene(self): # 遍历并删除所有矩形项 for item in list(self.items()): if isinstance(item, QtWidgets.QGraphicsRectItem): self.removeItem(item) self.graphics_line = None
- 修正
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
相关产品推荐
相关产品推荐

