Mahasish
Mahasish

Reputation: 190

How to use looping in Tkinter

I have tried to accomplish the same problem using two different type of solutions. In my first solution I am able to see the window after the complete while loop is executed i.e after the count value becomes 5 while in my second solution I am getting window created first and then the value of count is incrementing.

My first solution :

from Tkinter import *
import time

root = Tk()

count =0
def counter():
  global count
  while(count<5):
      Label(root, text=count).pack()
      time.sleep(2)
      count += 1

count = counter()
root.mainloop()

My second solution:

from Tkinter import *

count = 0 
def counter_label(label):
  def counter():
    global count
    count += 1
    label.config(text=str(count))
    label.after(2000, counter)
  counter()

root = Tk()
label = Label(root, fg="red")
label.pack()
counter_label(label)
root.mainloop()

Is there any standard method of looping in Tkinter in which looping takes place even after the window is created?? My second solution doesn't seems to be standard and is just calling a function after a fixed amount of time.

Upvotes: 0

Views: 15200

Answers (3)

Amal
Amal

Reputation: 33

Your second solution will gradually consume all the memory in your system because every after every 2000 milliseconds a new call stack is created.

Upvotes: 0

mgilson
mgilson

Reputation: 309821

I think that maybe something like this might be what you want:

import Tkinter as tk

class UpdateLabel(tk.Label):
  def __init__(self, *args, **kwargs):
    tk.Label.__init__(self, *args, **kwargs)
    self._count = 0

  def update_text(self):
    self.config(text=str(self._count))
    self._count += 1
    self.after(2000, self.update_text)

root = tk.Tk()
label = UpdateLabel(root)
label.pack()
label.update_text()
root.mainloop()

This will have the label count up from 0 to infinity -- incrementing every 2 seconds. Of course, you can always put a condition in update to stop counting at a certain point or whatever...

This isn't much different than your second example really ... I've just encapsulated the data in a class to make things a little nicer, but the idea is pretty much the same (having a function call itself "recursively"1 via after.)

Generally speaking, if you want an event to fire at particular intervals, Widget.after is the "standard" method that you're looking for.

1Note, it's not really calling itself recursively (which is good). It's registering itself to be called again at some later point in the Tkinter event loop.

Upvotes: 0

sbcondor
sbcondor

Reputation: 81

The difference is in the first example, time.sleep(2) does not yield control to the event loop, so all the pack() commands are queued up waiting for the event loop. You could call root.update() after each visible Tk change to let the event loop catch up on the queue:

from Tkinter import *
import time

root = Tk()

count =0
def counter():
  global count
  while(count<5):
      Label(root, text=count).pack()
      root.update() # allow window to catch up
      time.sleep(2)
      count += 1

count = counter()
root.mainloop()

Upvotes: 2

Related Questions