title: How can I update a Tkinter canvas in the middle of a function call?
body: <p>I'm writing Conway's game of life using Tkinter, and I want to have a "Go" button which allows the animation to begin, and continue stepping automatically until terminated. I'm using a Canvas to draw the environment, but since the "Go" button needs to complete the function call before it updates the canvas, the window just hangs until I kill the process. I've attempted to use <code>canvas.update_idletasks()</code> and <code>canvas.update()</code> (followed by a few seconds of sleeping) at points where I want to updated the canvas but that doesn't seem to do the trick. Any Ideas? Below is my GameOfLife class, the Environment class just manages the "board" of cells.</p>
  
  <pre><code>from Tkinter import *
  from random import *
  from time import time
  from Environment import *
  
  class GameOfLife(object):
      def __init__(self, master, envDim):
          self.unitSize = 10
          self.dimension = envDim * self.unitSize
          self.environment = Environment(envDim)
          self.environment.seedBoard()
          self.started = False
  
          frame = Frame(master)
          frame.pack()
          Button(frame, text = "Go", command = self.go_call).pack(side = LEFT)
          Button(frame, text = "Clear", command = self.reset_call).pack(side = LEFT)
          Button(frame, text = "Close", command = frame.quit).pack(side = RIGHT)
          canvas = self.drawCanvas(master, self.dimension)
  
  def drawCanvas(self, master, dimension):
      self.canvas = Canvas(master, width = self.dimension, height = self.dimension)
      self.canvas.pack()
      return self.canvas
  
  def go_call(self):
      print "&lt;&lt; Go Call &gt;&gt;"
      if self.environment.started == False:
          self.environment.seedBoard()
  
      self.drawState(self.environment)
      self.environment.nextBoard()
      self.started = True
      while True:
          self.environment.nextBoard()
          self.canvas.delete(ALL)
          self.drawState(self.environment)
          self.canvas.update_idletasks()
          sleep(4)
  
  def reset_call(self):
      print "&lt;&lt; Reset Call &gt;&gt;"
      self.canvas.delete(ALL)
      self.environment = Environment(self.environment.dim)
  
  def drawState(self, environment):
      size = self.unitSize
      for x in range(environment.dim):
          for y in range(environment.dim):
              if environment.matrix[x][y].alive == True:
                  xs = x * size
                  ys = y * size
                  self.canvas.create_rectangle(xs, ys, xs+size, ys+size, fill = 'black')
  
  envDim = 70
  root = Tk()
  gol = GameOfLife(root, envDim)
  root.mainloop()
  </code></pre>