Reputation: 3
import tkinter as tk
task = ["Sire, a villager is asking for additional rations, saying her children are starving"]
root = tk.Tk()
root.title("Test")
root.geometry("900x400")
x = tk.StringVar()
problem = tk.Label(root, textvariable=x, bg='white')
problem.place(rely = 0.5, relx= 0.5, anchor="center")
def show():
for i in range(len(task[0])+1):
root.after(i*500, lambda: x.set(task[0][0:i]))
b = tk.Button(root, text="Go", bg='white', command=show)
b.place(rely = 0.6, relx = 0.5, anchor="center")
root.configure(background='white')
root.mainloop()
When I run the program and click the button, the message only appears once instead of gradually.
Upvotes: 0
Views: 46
Reputation: 386010
The reason is that you aren't creating a closure. Therefore, when the first call to after
is triggered, the whole loop has finished and i
will be set to the length of the string. Your lambda uses the current value of i
, so it will always be the last value from the loop.
A really simple solution is to use the current value of i
as the default value for a parameter to your lambda function, like this:
root.after(i*500, lambda i=i: x.set(task[0][0:i]))
However, that's way more complicated than it needs to be. after
lets you add positional parameters so you don't need lambda
at all. You can simply that statement down to this:
root.after(i*500, x.set, task[0][0:i])
Upvotes: 1