好的,所以我只是想弄清楚为什么我的代码不像我想象的那样工作。
我正在构建一个GUI,我想在具有文本变量的Label
上显示文本。我已经创建了一个函数,该函数在调用时更新Label,但这当然不是我的问题。
我的问题源于我试图实现"一次打印一个字母"类型的标签。虽然它以我想要的方式打印到终端,但标签小部件只在整个函数完成后更新(从视觉上看,它与每次打印整个字符串而不是打印一个字母相同)。
那么我错过了什么,我不明白什么?你们能帮帮我吗?让我张贴一些代码,这样你们就可以看到我的错误在哪里。
我分别尝试了这两种方法,它们都给了我相同的结果,这不是我想要的。
def feeder(phrase):
"""Takes a string and displays the content like video game dialog."""
message = ""
for letter in phrase:
time.sleep(.15)
message += letter
information.set(message)
#print message
def feeder2(phrase):
"""Same as feeder, but trying out recursion"""
current.index += 1
if current.index <= len(phrase):
information.set(phrase[:current.index])
time.sleep(.1)
feeder2(current.status())
我不确定我是否需要发布更多的代码,所以你们可以更好地理解,但如果是这种情况,我会这样做。
这两个函数在这个函数
中使用def get_info():
"""This function sets the textvariable information."""
#information.set(current)
feeder2(current.status())
在这个函数
中使用def validate():
""" This function checks our guess and keeps track of our statistics for us. This is the function run when we press the enter button. """
current.turn += 1
if entry.get() == current.name:
if entry.get() == "clearing":
print "Not quite, but lets try again."
current.guesses -= 1
if entry.get() != "clearing":
print "Great Guess!"
current.points += 1
else:
print "Not quite, but lets try again."
current.guesses -= 1
print current
get_info()
entry.delete(0, END)
current.name = "clearing"
每次进入事件循环时,UI都会更新。这是因为绘制是通过事件完成的(也被称为"空闲任务",因为它们是在UI空闲时完成的)。
您的问题是:当您编写循环并执行time.sleep
时,在循环运行时不会进入事件循环,因此不会发生重绘。
你至少可以用几种不同的方法来解决你的问题。首先,你可以调用update_idletasks
来刷新屏幕。这将解决重绘问题,但由于你正在睡眠,UI将在循环期间无响应(因为按钮和按键不是"空闲任务")。
另一个解决方案是编写一个函数,该函数接受一个字符串,从字符串中取出一个字符并将其添加到小部件中。然后,它安排自己通过事件循环再次被调用。例如:
import Tkinter as tk
class App(tk.Tk):
def __init__(self,*args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.label = tk.Label(self, text="", width=20, anchor="w")
self.label.pack(side="top",fill="both",expand=True)
self.print_label_slowly("Hello, world!")
def print_label_slowly(self, message):
'''Print a label one character at a time using the event loop'''
t = self.label.cget("text")
t += message[0]
self.label.config(text=t)
if len(message) > 1:
self.after(500, self.print_label_slowly, message[1:])
app = App()
app.mainloop()
这种类型的解决方案保证你的UI保持响应,同时仍然在循环中运行你的代码。只是,不是使用显式循环,而是将工作添加到已经运行的事件循环中。