Переполнение памяти (?) Сбой на tkinter - PullRequest
0 голосов
/ 11 октября 2018

Я делаю игру для себя.Проблема, с которой я застрял, заключается в том, что по какой-то причине происходит сбой программы после помещения некоторых объектов на холст и их удаления.Более подробно:

У меня есть рамка FrameMain с холстом.

У меня есть рамка FrameLower с холстом.Также изображение на холсте.

Я помещаю и удаляю несколько FrameLower как FrameMain.obj на FrameMain канве с методом FrameMain.__placeFrames().

Проблема в том, что это похоже на памятьгде-то не очищается полностью, когда я удаляю FrameMain.obj.Так что это приводит к сбою программы через некоторое время, в зависимости от того, сколько раз FrameLower размещено и сколько изображений у нее на холсте.

У меня достаточно свободной оперативной памяти, как вы можете предсказать, ~ 6 ГБ, так что это не проблема.

Что я действительно хочу понять, так это то, почему происходит сбой, если имеется свободная память для хранения объектов, и почему эти объекты не удаляются полностью.

Что ядействительно хочу сделать, это избавиться от этой аварии.В следующем упрощенном примере я размещаю 10000 кадров, но в реальной программе 100 из них достаточно, чтобы убить мою игру - они сильно заполнены изображениями.

(Для того, чтобы этот код работал как есть, любойimg.gif файл в корневом каталоге необходим)

from tkinter import *

class FrameMain(Frame):
    def __init__(self,master):
        super().__init__(master,height=100,width=100,bg='black')
        self.grid()

        self.canvas=Canvas(self,height=100,width=100,bg='white')
        self.canvas.grid()

        self.__placeFrames(10000)

    def __placeFrames(self,number):
        for counter in range(0,number):
            self.obj=self.canvas.create_window(50,50,window=FrameLower(self.canvas))
            self.canvas.delete(self.obj)
            del self.obj



class FrameLower(Frame):
    def __init__(self,master):
        super().__init__(master,height=50,width=50,bg='red')

        self.canvas=Canvas(self,height=50,width=50,bg='blue')
        self.canvas.grid()

        self.img=PhotoImage(file='img.gif')
        self.canvas.create_image(0,0,image=self.img)

def Run():
    root=Tk()
    frameMain=FrameMain(root)
    root.mainloop()

Run()

1 Ответ

0 голосов
/ 11 октября 2018

Когда вы делаете self.canvas.delete(self.obj), все, что вы делаете, это удаляете объект с холста.Кадр, связанный с объектом, не будет уничтожен.Если вы хотите уничтожить объект окна, вам нужно явно вызвать destroy для него.

У холста также есть некоторые известные ограничения при создании тысяч и тысяч элементов.Он не перерабатывает идентификаторы элементов холста, поэтому они продолжают занимать небольшое количество памяти, даже если сам объект холста был удален.Одно из решений этой проблемы - не удалять элементы холста, а перемещать их за пределы экрана или настраивать их скрытие, когда они не нужны, а затем перенастраивать их вместо создания нового элемента.

...