title: "after" looping indefinitely: never entering mainloop
body: <p>This is my first post. I started coding when considering a career swap two months ago and am working on a Tetris clone. I've implemented most of the core features, but cannot get the game to refresh continually with an after loop. </p>
  
  <p>I'm using Tkinter to produce my Gui and am trying out event oriented programming. </p>
  
  <p>My understanding is that <code>after(Time, Event)</code> from <code>Tkinter</code> should schedule whatever the <code>Event</code> callback function is to occur after a delay specified by <code>Time</code>. I think that the code is supposed to continue executing subsequent items after this. </p>
  
  <p>My frame refresh function (<code>game.updateBoard()</code>) does most of the necessary events for tetris to work, then calls itself using after. I call it once when initializing an instance of the game. </p>
  
  <p>Instead of proceeding to <code>mainloop()</code>, the <code>game.updateboard()</code> function calls itself via <code>after</code> indefinitely. </p>
  
  <p>I suspect that it is not behaving how I thought <code>after</code> worked which would be to continue to execute the script until the specified delay occurs. I think it is waiting for the callback to terminate to continue. </p>
  
  <p>I tried to find a resource on this but could not. </p>
  
  <p>If you have suggestions for fixing this question, the attached code, or for coding in general, I am very happy to hear them! This is a learning process and I'll gladly try pretty much anything you suggest.</p>
  
  <p>Here is the relevant portion of the code:</p>
  
  <pre><code>class game():
      def __init__(self): #Set up board and image board
          self.pieces = ["L","J","S","Z","T","O","I"]
          self.board = boardFrame()
          self.root = Tk()
          self.root.title("Tetris")
          self.root.geometry("250x525")
  
          self.frame = Frame(self.root)
  
          #set up black and green squares for display
          self.bSquare = "bsquare.gif"
          self.gSquare = "square.gif"
          self.rSquare = "rsquare.gif"
          self.image0 = PhotoImage(file = self.bSquare)
          self.image1 = PhotoImage(file = self.gSquare)
          self.image2 = PhotoImage(file = self.rSquare)
  
          #get an initial piece to work with
          self.activeBlock = piece(self.pieces[random.randint(0,6)])
  
          #Tells program to lower block every half second
          self.blockTimer = 0
          self.updateBoard()
  
          self.root.bind('&lt;KeyPress-Up&gt;', self.turn)
          self.root.bind('&lt;KeyPress-Right&gt;', self.moveR)
          self.root.bind('&lt;KeyPress-Left&gt;', self.moveL)
          self.root.bind('&lt;KeyPress-Down&gt;',self.moveD)
          print("Entering mainloop")
          self.root.mainloop()
  
      def turn(self, event):
          self.activeBlock.deOccupy(self.board)
          self.activeBlock.turn()
          self.activeBlock.occupy(self.board)
          self.drawGrid(self.board.grid)
  
      def moveR(self, event):
          self.activeBlock.deOccupy(self.board)
          self.activeBlock.updatePos([1,0], self.board)
          self.activeBlock.occupy(self.board)
          self.drawGrid(self.board.grid)
  
      def moveL(self, event):
        if self.activeBlock.checkLeft(self.board) == False:
          self.activeBlock.deOccupy(self.board)
          self.activeBlock.updatePos([-1,0], self.board)
          self.activeBlock.occupy(self.board)
          self.drawGrid(self.board.grid)
  
      def moveD(self, event): #find
          self.activeBlock.deOccupy(self.board)
          self.activeBlock.updatePos([0,-1],self.board)
          if self.activeBlock.checkBottom(self.board) == True:
              self.activeBlock.occupy(self.board)
              self.activeBlock = piece(self.pieces[random.randint(0,6)])
  ##            self.activeBlock = piece(self.pieces[1])
              print("bottomed")
              self.activeBlock.occupy(self.board)
  
          self.activeBlock.occupy(self.board)
          self.drawGrid(self.board.grid)
  
      def drawGrid(self, dGrid):
  
          #Generate squares to match tetris board
          for widget in self.frame.children.values():
              widget.destroy()
  
          self.activeBlock.occupy(self.board)
  
          for x in range(9,-1,-1):
              for y in range(20,-1,-1):
                  if self.board.grid[x][y] == 1:
                      self.frame.displayA = Label(self.frame, image=self.image1)
  ##                    self.frame.displayA.image = self.image1
                      self.frame.displayA.grid(row=21-y, column=x)
  
  
                  else:
                      self.frame.displayA = Label(self.frame, image = self.image0)
  ##                    self.frame.displayA.image = self.image0
                      self.frame.displayA.grid(row=21-y, column=x)
  
          self.frame.displayA = Label(self.frame, image = self.image2)
          self.frame.displayA.grid(row = 21 - self.activeBlock.center[1], column = self.activeBlock.center[0])
  
          self.frame.grid()
  
      def updateBoard(self):
          self.blockTimer += 1
          "print updateBoard Loop"
  
          ## 1)check for keyboard commands
          #1.1 move block by keyboard commands
          #2) see if block has bottomed out, if it has, have it enter itself into the grid and generate a new block.
          if self.activeBlock.checkBottom(self.board) == True:
              self.activeBlock.occupy(self.board)
              self.activeBlock = piece(self.pieces[random.randint(0,6)])
              print("bottomed")
              self.activeBlock.occupy(self.board)
  
          #2.2 - if block has not bottomed and 50 frames (~.5 seconds) have passed, move the active block down a square after clearing its old space. 
          elif self.blockTimer%12 == 0:
              self.activeBlock.deOccupy(self.board)
              self.activeBlock.updatePos([0,-1], self.board)
              self.activeBlock.occupy(self.board)
  
  
      ## 4) check for filled rows
          for y in range(1,21):
              for x in range(10):
                  rowFull = True
                  if self.board.grid[x][y] == 0:
                      rowFull == False  
              #4.1 if any row is filled, delete it and then move all rows above the deleted row down by one
              if rowFull == True:
                  for x2 in range(10):
                      self.board.grid[x2][y] = 0
                      for y2 in range(y+1,21):
                          if self.board.grid[x2][y2] == 1:
                              self.board.grid[x2][y2] = 0
                              self.board.grid[x2][y2-1] = 1
  
              #4.11 if the row is full and the row above it was full, delete the row again as well as the row above it, and move all rows down by 2
                  for x in range(10):
                      rowFull = True
                      if self.board.grid[x][y] == 0:
                          rowFull == False
                          if rowFull == True:
                              for x2 in range(10):
                                  try:
                                      self.board.grid[x2][y] = 0
                                      self.board.grid[x2][y+1] = 0
                                  except:
                                      pass
                                  for y2 in range(y+2,21):
                                      try:
                                          if self.board.grid[x2][y2] == 1:
                                              self.board.grid[x2][y2] = 0
                                              self.board.grid[x2][y2-2] = 1
                                      except:
                                          pass
  
  
          #5) if there is a block in the top row, end the game loop
          for x in range(10):
              if self.board.grid[x][20] == 1:
                  game = "over"
  
  
          #6) update image
          self.activeBlock.occupy(self.board)
          self.drawGrid(self.board.grid)
          self.frame.after(500, self.updateBoard())
  
  
  Game = game()
  </code></pre>