RuntimeError: внутренний объект C ++ (PySide2.QtWidgets.QGraphicsPixmapItem) уже удален - PullRequest
0 голосов
/ 16 мая 2019

У меня есть средство визуализации кадров класса

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..Это правильно, потому что я создаю новый объект симуляции, когда нажата кнопка «начало», но он также передается конструктору, что означает, что он не должен ссылаться на мою старую симуляцию.Я не уверен, почему воссоздание ресурсов не позволяет мне рисовать снова

Я попытался явно установить фрейм-рендерер на None, пытаясь вывести его из области видимости, но это, похоже, не помогает

1 Ответ

0 голосов
/ 17 мая 2019

Установка графической сцены на None не была достаточной для запуска Qt, чтобы запустить работающий деконструктор c ++.Чтобы удалить сцену, мне пришлось сначала очистить сцену , а затем удалить ее

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