我有一个tkinter Entry小部件,当用户按下按钮时,内容会更新:
from tkinter import *
window = Tk()
def abcdef(num):
ent.config(state=NORMAL)
ent.delete(0, 'end')
ent.insert(0, num)
ent.config(state = "readonly")
print(num) #Just to check the code is being run
def changeEntry():
for j in range(3):
ent.after(1000, abcdef(j))
ent = Entry(widow, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")
btn = Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)
window.mainloop()
当我按下按钮时,窗口会冻结3秒钟,然后只显示最终的数字。当用户按下按钮时,我怎么能这样做,条目每秒都会改变,而不是仅仅冻结3秒而只显示最后一个?
提前致谢
答案 0 :(得分:2)
.after
电话有两个问题。 .after
方法告诉Tkinter在经过时间间隔后调用您传递的函数。但是你告诉Tkinter在1000毫秒过后做了3件事,所以他们都会发生在彼此之上。所以你需要错开延迟。
其次,你需要给.after
一个函数来调用它的时间。但是您的代码调用该函数并为.after
提供函数的返回值。我们可以通过将函数调用包装在另一个函数中来解决这个问一种方便的方法是使用lambda
,为lambda
提供一个可以传递给abcdef
的默认参数
import tkinter as tk
window = tk.Tk()
def abcdef(num):
ent.config(state=tk.NORMAL)
ent.delete(0, 'end')
ent.insert(0, num)
ent.config(state = "readonly")
print(num) #Just to check the code is being run
def changeEntry():
for j in range(3):
ent.after(1000 * j, lambda num=j: abcdef(num))
ent = tk.Entry(window, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")
btn = tk.Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)
window.mainloop()
我还用整理器import tkinter as tk
替换了那个“星际”导入。这很明显哪些名字来自Tkinter,哪些名字是你的程序的本地名称。
Bryan Oakley指出我们不需要lambda
,我们可以在函数名后传入参数。有关详细信息,请参阅Tkinter文档中的Basic Widget Methods。所以我们可以像这样重写changeEntry
:
def changeEntry():
for j in range(3):
ent.after(1000 * j, abcdef, j)
谢谢,布莱恩!