RuntimeError:内部C ++对象(PySide2.QtWidgets.QGraphicsPixmapItem)已删除

时间:2019-05-16 02:46:57

标签: python pyside2

我有一个类框架渲染器

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()

为了进行测试,我只是让我的像素图随机移动。从第二个类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.。这是正确的,因为在按下begin时确实创建了一个新的模拟对象,但它也传递给了构造函数,这意味着它不应引用我的旧模拟对象。我不确定为什么重新创建资产不会让我再次绘画

我试图将帧渲染器显式设置为None,试图将其超出范围,但这似乎无济于事

1 个答案:

答案 0 :(得分:0)

将图形场景设置为None不足以触发Qt导致底层c ++解构函数运行。为了删除场景,我必须先清空场景然后删除它

for item in self.graphicsScene.items():
    self.graphicsScene.removeItem(item)