RuntimeError: Internal C++ object (PySide2.QtWidgets.QGraphicsPixmapItem) already deleted
RuntimeError: Internal C++ object (PySide2.QtWidgets.QGraphicsPixmapItem) already deleted
我有一个 class 帧渲染器
class FrameRenderer():
simulation = None
scene = None
timer = None
def __init__(self, simulation, scene):
self.simulation = simulation
self.scene = scene
self.timer = QTimer()
self.timer.timeout.connect(self.nextFrame)
self.timer.setInterval(1000/30)# 30 Frames per second
#Render one time step
def nextFrame(self):
for food in self.simulation.food:
food.xPos = food.xPos + randint(-1,1)
food.yPos = food.yPos + randint(-1,1)
if food.pixmap:
food.pixmap.setPos(food.xPos, food.yPos)
def start(self):
self.timer.start()
def pause(self):
self.timer.stop()
为了测试,我只是让我的像素图随机移动。它是从第二个 class SimulationView
调用的
class SimulationView():
mainWindow = None
graphicsScene = None
simWindow = None
simulation = None
isSimulating = False
simulationStarted = False
frameRenderer = None
beginSimulationButton = None
cancelSimulationButton = None
toggleSimulationButton = None
foodSlider = None
BUFFER = 10 #ensure we don't drop items too close to the extremes of the scene
def __init__(self, mainWindow):
self.mainWindow = mainWindow
self.simWindow = mainWindow.simulation_window
#connect QWidgets to functions
self.beginSimulationButton = mainWindow.begin_simulation_button
self.beginSimulationButton.clicked.connect(self.simulate)
self.cancelSimulationButton = mainWindow.cancel_simulation_button
self.cancelSimulationButton.clicked.connect(self.cancelSimulation)
self.toggleSimulationButton = mainWindow.toggle_simulation_button
self.toggleSimulationButton.clicked.connect(self.toggleSimulation)
self.foodSlider = mainWindow.food_slider
def createGraphicsScene(self):
#create new scene
self.graphicsScene = QGraphicsScene()
self.graphicsScene.setSceneRect(self.simWindow.x(), self.simWindow.y(), self.simWindow.width() - self.BUFFER, self.simWindow.height() - self.BUFFER)
self.simWindow.setScene(self.graphicsScene)
#draw the food items to the screen and create new food objects
def drawFood(self, foodAmount):
for _ in range(foodAmount):
food_x = randint(self.BUFFER, self.graphicsScene.width() - self.BUFFER)
food_y = randint(self.BUFFER, self.graphicsScene.height() - self.BUFFER)
newFood = Food(food_x,food_y)
self.simulation.addFood(newFood)
self.graphicsScene.addItem(newFood.pixmap)
newFood.pixmap.setPos(food_x, food_y)
#call the correct function based on the simulation state
def simulate(self):
self.start()
self.isSimulating = True
self.simulationStarted = True
#start the simulation
def start(self):
self.createGraphicsScene()
self.simulation = Simulation(self.mainWindow)
self.frameRenderer = FrameRenderer(self.simulation, self.graphicsScene)
self.drawFood(self.foodSlider.sliderPosition())
self.frameRenderer.start()
#toggle whether or not we are current simulating
def toggleSimulation(self):
if not self.simulationStarted:
return
if self.isSimulating:
self.frameRenderer.pause()
else:
self.frameRenderer.start()
self.isSimulating = not self.isSimulating
#clear sim window
def cancelSimulation(self):
self.frameRenderer = None
self.simulation = None
self.createGraphicsScene()
self.isSimulating = False
self.simulationStarted = False
代码工作正常,直到我取消然后重新开始模拟。如果我这样做,我会得到 RuntimeError: Internal C++ object (PySide2.QtWidgets.QGraphicsPixmapItem) already deleted.
。这是正确的,因为我确实在按下开始时创建了一个新的模拟对象,但它也被传递给了构造函数,这意味着它不应该引用我的旧模拟。我不确定为什么重新创建资产不会让我再次绘制
我曾尝试将帧渲染器显式设置为 None 试图将其置于范围之外,但这似乎无济于事
将图形场景设置为 None
不足以触发 Qt 导致底层 c++ 解构器为 运行。为了让场景被删除,我必须先清空场景 然后 删除它
for item in self.graphicsScene.items():
self.graphicsScene.removeItem(item)
我有一个 class 帧渲染器
class FrameRenderer():
simulation = None
scene = None
timer = None
def __init__(self, simulation, scene):
self.simulation = simulation
self.scene = scene
self.timer = QTimer()
self.timer.timeout.connect(self.nextFrame)
self.timer.setInterval(1000/30)# 30 Frames per second
#Render one time step
def nextFrame(self):
for food in self.simulation.food:
food.xPos = food.xPos + randint(-1,1)
food.yPos = food.yPos + randint(-1,1)
if food.pixmap:
food.pixmap.setPos(food.xPos, food.yPos)
def start(self):
self.timer.start()
def pause(self):
self.timer.stop()
为了测试,我只是让我的像素图随机移动。它是从第二个 class SimulationView
调用的class SimulationView():
mainWindow = None
graphicsScene = None
simWindow = None
simulation = None
isSimulating = False
simulationStarted = False
frameRenderer = None
beginSimulationButton = None
cancelSimulationButton = None
toggleSimulationButton = None
foodSlider = None
BUFFER = 10 #ensure we don't drop items too close to the extremes of the scene
def __init__(self, mainWindow):
self.mainWindow = mainWindow
self.simWindow = mainWindow.simulation_window
#connect QWidgets to functions
self.beginSimulationButton = mainWindow.begin_simulation_button
self.beginSimulationButton.clicked.connect(self.simulate)
self.cancelSimulationButton = mainWindow.cancel_simulation_button
self.cancelSimulationButton.clicked.connect(self.cancelSimulation)
self.toggleSimulationButton = mainWindow.toggle_simulation_button
self.toggleSimulationButton.clicked.connect(self.toggleSimulation)
self.foodSlider = mainWindow.food_slider
def createGraphicsScene(self):
#create new scene
self.graphicsScene = QGraphicsScene()
self.graphicsScene.setSceneRect(self.simWindow.x(), self.simWindow.y(), self.simWindow.width() - self.BUFFER, self.simWindow.height() - self.BUFFER)
self.simWindow.setScene(self.graphicsScene)
#draw the food items to the screen and create new food objects
def drawFood(self, foodAmount):
for _ in range(foodAmount):
food_x = randint(self.BUFFER, self.graphicsScene.width() - self.BUFFER)
food_y = randint(self.BUFFER, self.graphicsScene.height() - self.BUFFER)
newFood = Food(food_x,food_y)
self.simulation.addFood(newFood)
self.graphicsScene.addItem(newFood.pixmap)
newFood.pixmap.setPos(food_x, food_y)
#call the correct function based on the simulation state
def simulate(self):
self.start()
self.isSimulating = True
self.simulationStarted = True
#start the simulation
def start(self):
self.createGraphicsScene()
self.simulation = Simulation(self.mainWindow)
self.frameRenderer = FrameRenderer(self.simulation, self.graphicsScene)
self.drawFood(self.foodSlider.sliderPosition())
self.frameRenderer.start()
#toggle whether or not we are current simulating
def toggleSimulation(self):
if not self.simulationStarted:
return
if self.isSimulating:
self.frameRenderer.pause()
else:
self.frameRenderer.start()
self.isSimulating = not self.isSimulating
#clear sim window
def cancelSimulation(self):
self.frameRenderer = None
self.simulation = None
self.createGraphicsScene()
self.isSimulating = False
self.simulationStarted = False
代码工作正常,直到我取消然后重新开始模拟。如果我这样做,我会得到 RuntimeError: Internal C++ object (PySide2.QtWidgets.QGraphicsPixmapItem) already deleted.
。这是正确的,因为我确实在按下开始时创建了一个新的模拟对象,但它也被传递给了构造函数,这意味着它不应该引用我的旧模拟。我不确定为什么重新创建资产不会让我再次绘制
我曾尝试将帧渲染器显式设置为 None 试图将其置于范围之外,但这似乎无济于事
将图形场景设置为 None
不足以触发 Qt 导致底层 c++ 解构器为 运行。为了让场景被删除,我必须先清空场景 然后 删除它
for item in self.graphicsScene.items():
self.graphicsScene.removeItem(item)