My code (see below) is supposed to display a start/stop button, a scale button to select the speed of the visualization and a canvas with many rectangles that randomly change color with time.
When I run this piece of code, the memory usage increases dramatically with time (if you run, you need to increase the speed to about 10 to see it more easily). At work (on a Windows 7 workstation) where I tested it at first it becomes essentially unusable (it become very very slow) after few minutes while on my Mac laptop it survives a bit longer although the memory usage increases steadily.
After having looked for the culprit, I have come across multiple threads including this one from Tk Toolkit that dates back to 2010 where they mention that there is a problem with itemconfigure()
when it is used to change color, which is exactly what I am doing.
Commenting the "self.update_canvas()"
function in the self.run_InfiniteT_MC()
function solves the problem as far as I can see and seems to agree with the diagnostic that itemconfigure()
to change color may still be problematic.
Note that I have also tried to delete the changing rectangles via the command "self.canvas.delete(self.rect[i])" and then re-creating them but that does not change my memory problem at all.
I have also tried to destroy the whole canvas via "self.canvas.destroy()"
and recreating everything from scratch each time in need to update the image but again that fails to solve my memory problem.
Is there anything that I can do to solve this memory problem without changing my whole code (here this just a small piece of it)?
EDIT: After indenting properly the command self.after
, the problem disappeared; so the itemconfigure()
command is not to blame at all, at least not for this 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()
Aucun commentaire:
Enregistrer un commentaire