【问题标题】:Change tkinter entry widget multiple times after pressing a button按下按钮后多次更改 tkinter 条目小部件
【发布时间】:2018-05-27 18:46:04
【问题描述】:

我有一个 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 秒并且只显示最后一个?

提前致谢

【问题讨论】:

标签: python python-3.x tkinter tkinter-entry


【解决方案1】:

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

谢谢,布莱恩!

【讨论】:

  • 在这种特定情况下,您不需要在对 after 的调用中使用 lambda。你可以传入额外的参数:ent.after(1000*j, abcdef, j).
  • @BryanOakley 有趣!我依稀记得,但我查了文档,他们没有提到,所以我想我一定是在想象事情。 ;) 更正:我检查了事件文档,而不是 .after 文档。但我会更新我的答案。谢谢!
猜你喜欢
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-18
  • 2011-01-16
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多