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

PyQt6中删除QPainter绘制图形的Widget后图形未消失的问题

问题解决:删除QWidget后绘制内容未消失

问题根源

你当前删除PlayerToken的方式有误:

  • Qt的父子对象机制中,当QWidget有父对象时,父窗口会维护子对象的引用,仅通过self.playerToken = None和del self.playerToken无法真正销毁该Widget,它仍然存在于父窗口的子对象列表中,所以绘制的圆形不会消失。
  • 调用父窗口的update()无效,因为Widget本身还没被销毁,父窗口重绘时依然会绘制这个未被移除的子Widget。

正确解决方案

要彻底销毁Qt Widget,需调用Widget的deleteLater()方法,该方法会告知Qt事件循环在合适的时机销毁Widget,同时将其从父窗口的子对象列表中移除,自动触发界面重绘。

修改MainWindow的Remove方法如下:

def Remove(self):
    if self.playerToken:
        self.playerToken.deleteLater()
        self.playerToken = None  # 清空本地引用
    print('Remove exiting')

额外优化点

  1. 你的PlayerToken的paintEvent存在冗余代码:painter = QPainter(self)已经完成了painter的初始化,不需要再调用painter.begin(self),而且painter = None是多余的(Python会自动管理内存)。修改后的paintEvent更简洁:
def paintEvent(self, event : QPaintEvent) -> None:
    event.accept()
    painter = QPainter(self)
    painter.translate(self.SIZE, self.SIZE)
    painter.setBrush(QBrush(QColor(self.colour), Qt.BrushStyle.SolidPattern))
    painter.drawEllipse(QPointF(0, 0), self.SIZE, self.SIZE)
  1. 初始化时的self.update()可以去掉,Widget显示时会自动触发paintEvent。

修改后的完整代码

from __future__ import annotations
import typing
from PyQt6.QtGui import QPaintEvent, QPainter, QColor, QBrush
from PyQt6.QtWidgets import QWidget
from PyQt6.QtCore import Qt, QPoint, QPointF, QSize

class PlayerToken(QWidget):
    SIZE = 12

    def __init__(self, parent, colour):
        super(PlayerToken, self).__init__(parent)
        self.setMinimumSize(QSize(self.SIZE*2, self.SIZE*2))
        self.colour = colour

    def move(self, where : QPoint):
        centrePos = QPoint(where.x() - self.SIZE, where.y() - self.SIZE)
        super().move(centrePos)

    def paintEvent(self, event : QPaintEvent) -> None:
        event.accept()
        painter = QPainter(self)
        painter.translate(self.SIZE, self.SIZE)
        painter.setBrush(QBrush(QColor(self.colour), Qt.BrushStyle.SolidPattern))
        painter.drawEllipse(QPointF(0, 0), self.SIZE, self.SIZE)

if __name__ == "__main__":
    from PyQt6.QtWidgets import QApplication, QMainWindow
    from PyQt6.QtCore import QSize, QTimer

    class MainWindow(QMainWindow):
        def __init__(self,  *args, **kwargs):
            super(MainWindow, self).__init__( *args, **kwargs)
            self.setMinimumSize(QSize(400, 500))
            self.playerToken = PlayerToken(self, 'red')
            self.playerToken.move(QPoint(100, 300))
            self.playerToken.show()
            QTimer.singleShot(5*1000, self.Remove)

        def Remove(self):
            if self.playerToken:
                self.playerToken.deleteLater()
                self.playerToken = None
            print('Remove exiting')

    app = QApplication([])
    mainWindow = MainWindow()
    mainWindow.show()
    retCode = app.exec()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:09:51