为什么我的root.after命令不能循环工作?

时间:2020-04-14 18:03:59

标签: python-3.x tkinter

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()

当我运行程序并单击按钮时,该消息仅出现一次,而不是逐渐出现。

1 个答案:

答案 0 :(得分:1)

原因是您没有创建闭包。因此,当触发对after的第一次调用时,整个循环已完成,并且i将设置为字符串的长度。您的lambda使用i的当前值,因此它始终是循环中的最后一个值。

一个非常简单的解决方案是使用i的当前值作为lambda函数的参数的默认值,如下所示:

root.after(i*500, lambda i=i: x.set(task[0][0:i]))

但是,这比需要的复杂得多。 after允许您添加位置参数,因此根本不需要lambda。您可以简单地将此语句简化为:

root.after(i*500, x.set, task[0][0:i])