Mein Code (siehe unten) soll eine Start/Stop-Taste, eine Skalentaste zur Auswahl der Geschwindigkeit der Visualisierung und eine Leinwand mit vielen Rechtecken anzeigen, die zufällig die Farbe mit der Zeit ändern.Itemconfigure() und Speicherverlust mit tkinter
Wenn ich diesen Codeabschnitt ausführe, erhöht sich die Speichernutzung dramatisch mit der Zeit (wenn Sie ausführen, müssen Sie die Geschwindigkeit auf etwa 10 erhöhen, um es einfacher zu sehen). Bei der Arbeit (auf einer Windows 7-Workstation), wo ich es zuerst getestet habe, wird es nach wenigen Minuten praktisch unbrauchbar (es wird sehr langsam), während es auf meinem Mac-Laptop ein wenig länger überlebt, obwohl die Speicherauslastung stetig steigt.
Nach dem Täter sah zu haben, ich habe über mehrere Threads kommen einschließlich this one von Tk-Toolkit, das bis 2010 zurück geht, wo sie erwähnen, dass es ein Problem mit itemconfigure()
ist, wenn es verwendet wird, die Farbe zu ändern, das ist genau das, was ich mache ich.
die "self.update_canvas()"
Funktion in der self.run_InfiniteT_MC()
Funktion löst so weit das Problem kommentiert ich sehen kann und scheint mit dem Diagnose zu bestätigen, dass itemconfigure()
Farbe ändern noch problematisch sein kann.
Beachten Sie, dass ich auch versucht habe, die sich ändernden Rechtecke über den Befehl "self.canvas.delete (self.rect [i])" zu löschen und sie dann neu zu erstellen, aber das mein Speicherproblem überhaupt nicht ändert.
Ich habe auch versucht, die gesamte Leinwand über "self.canvas.destroy()"
zu zerstören und alles von Grund auf neu zu erstellen, jedes Mal in der Notwendigkeit, das Bild zu aktualisieren, aber das löst nicht mein Speicherproblem.
Gibt es etwas, was ich tun kann, um dieses Speicherproblem zu lösen, ohne meinen gesamten Code zu ändern (hier ist das nur ein kleiner Teil davon)?
EDIT: Nach dem Einrücken des Befehls self.after
ordnungsgemäß das Problem verschwand; so ist der itemconfigure()
Befehl überhaupt nicht schuld, zumindest nicht für dieses Problem.
from tkinter import *
from numpy import *
from random import randint
class Application(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.columnconfigure(0, pad = 10)
self.grid()
self.count = 0
self.create_widgets()
def create_widgets(self):
"create an array of cells all initiated with the same value"
self.nx = 70
self.ny = self.nx
self.ntot = self.nx*self.ny
self.state = [0 for x in range(self.ntot)]
for x in range(self.ntot):
self.state[x] = 0 #0 is down, 1 is right, 2 is up, 3 is left ...modulo 4
"create a scale button to choose speed of dynamics"
self.ScaleSpeedVar = IntVar
self.ScaleSpeed = Scale(self, from_=1, to =20, orient = HORIZONTAL, label = "SimuSpeed", variable = self.ScaleSpeedVar, font =('Helvetica','18'))
self.ScaleSpeed.grid()
self.ScaleSpeed.set(1)
"create a button that starts/stops the dynamics"
self.do_run = False
self.startclick = True
self.buttonStartStop = Button(self, text = "Start/Stop", font =('Helvetica','18'))
self.buttonStartStop["command"] = self.start_stop_simu
self.buttonStartStop.grid()
"create a big canva to contain the simulation cells"
self.size = 500
self.canvas = Canvas(self, width=self.size, height=self.size, bg ="red")
self.canvas.grid()
self.width = 1
self.rect = [0 for x in range(self.ntot)]
for i in range(self.ntot):
self.rectsize = self.size/self.nx
self.rect[i] = self.canvas.create_rectangle((i%(self.nx))*self.rectsize, self.rectsize*(i//self.nx), (i%(self.nx))*self.rectsize+self.rectsize, self.rectsize*(i//self.nx)+self.rectsize, fill="red", tag = i, width = self.width)
def start_stop_simu(self):
if self.startclick:
self.start_simu()
self.startclick = False
else :
self.stop_simu()
self.startclick = True
def start_simu(self):
self.do_run = True
self.run_InfiniteT_MC()
def stop_simu(self):
self.do_run = False
def run_InfiniteT_MC(self):
if self.do_run:
self.simuspeed = pow(2,self.ScaleSpeed.get())
for i in range(self.simuspeed):
self.cellID = randint(0,self.ntot-1)
self.angle = 2*randint(0,1)-1
self.state[self.cellID] = (self.state[self.cellID]+self.angle)%4
self.update_canvas()
self.after(1, self.run_InfiniteT_MC)
def update_canvas(self):
for i in range(self.ntot):
if self.state[i] == 0:
self.canvas.itemconfig(self.rect[i], fill = "red")
if self.state[i] == 2:
self.canvas.itemconfig(self.rect[i], fill = "blue")
if self.state[i] == 1:
self.canvas.itemconfig(self.rect[i], fill = "green")
if self.state[i] == 3:
self.canvas.itemconfig(self.rect[i], fill = "yellow")
self.canvas.update_idletasks()
root = Tk()
root.title("Problematic code")
root.geometry("800x600")
app = Application(root)
root.mainloop()
Wenn Sie die Farben in hex Werte ändern (zB: '" # ff0000 "' anstelle von '" rot "', hat das irgendeinen Effekt? –
das ist ein guter Punkt, ich werde das versuchen – gatsu