You need to enable JavaScript to run this app. 拖拽QGraphicsView内Item出现重影,需保留drawForeground该如何解决
优惠活动
大模型
产品
解决方案
定价
更多

拖拽QGraphicsView内Item出现重影,需保留drawForeground该如何解决

问题原因

重影问题由两个配置冲突导致:

  • 配置的QGraphicsView.BoundingRectViewportUpdate视口更新模式,只会在拖拽元素时重绘元素移动涉及的局部区域,不会刷新整个视口
  • drawForeground方法基于传入的局部更新矩形rect绘制边框,每次局部更新只会绘制当前区域对应的边框片段,之前绘制的旧边框没有被清除,层层叠加形成重影。
解决方法

方案1:修改视口更新模式(最简方案,仅需修改1行代码)

直接将视口更新模式改为全视口更新,每次触发重绘时都会刷新整个视图区域,自动清除旧的前景绘制内容:
把View初始化代码中的这行:

self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)

替换为:

self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

该方案足够应对绝大多数常规业务场景,不会产生明显的性能损失。

方案2:保留局部更新性能优化,调整drawForeground逻辑

如果你确实需要保留局部更新的性能优势,可以根据边框的业务定位修改绘制逻辑:

  • 如果边框需要固定在视图窗口边缘(不跟随场景拖拽、缩放移动),可以改为基于视图坐标绘制,避免和场景局部更新区域绑定:
def drawForeground(self, painter: QPainter, rect: QRectF):
    painter.save()
    # 重置坐标变换,使用视图视口的像素坐标
    painter.resetTransform()
    pen = QPen(QBrush(Qt.blue), 2, Qt.DotLine)
    painter.setPen(pen)
    # 直接基于视口大小绘制边框
    viewport_rect = self.viewport().rect()
    painter.drawRect(viewport_rect.adjusted(10, 10, -10, -10))
    painter.restore()
  • 如果边框需要绘制在场景的固定位置,只需要在元素移动时主动调用self.scene().invalidate()触发前景的全局刷新即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 05:15:04