My code (see below) should display a start / stop button, a zoom button to select a render speed and a canvas with many rectangles that randomly change color over time.
When I run this piece of code, memory usage increases dramatically over time (if you run, you need to increase the speed to 10 to see it easier). At work (on a Windows 7 workstation), where I tested it first, it becomes almost unusable (it becomes very slow) after a few minutes, while on my Mac laptop it survives a little longer, although memory usage is growing steadily.
After searching for the culprit, I came across several threads, including this one from the Tk Toolkit, which 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 do.
Commenting out a function "self.update_canvas()"in a function self.run_InfiniteT_MC()solves the problem as far as I can see, and seems to agree with the diagnostics, which itemconfigure()can be problematic for color changes.
Note that I also tried to delete the changing rectangles with the command self.canvas.delete (self.rect [i]) "and then recreate them, but that does not change the memory problem at all.
I also tried to destroy the entire canvas with "self.canvas.destroy()"and recreate everything from scratch every time you need to update the image, but again, that cannot solve the problem with my memory.
Is there anything I can do to solve this memory problem without changing all my code (here is just a small part)?
EDIT: after correct detuning of the command, the self.afterproblem disappeared; therefore, the team is itemconfigure()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
"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()