Reputation: 190
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
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
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
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