我在使用tkinter实现快速阅读器程序时遇到问题,这是因为它在约5秒后挂起。
我知道这是因为while循环但我没有找到解决问题的方法。也许在根主循环之外循环?
以下是代码:
import tkinter
import tkinter.ttk
import tkinter.filedialog
import tkinter.messagebox
class FastReader(object):
SLEEP_TIME = 250
def __init__(self):
self.filename = self.getFile()
self.running = True
def window(self):
self.root = tkinter.Tk()
self.root.wm_title("Fast Reader.")
self.text = tkinter.ttk.Label(self.root, text = "word")
self.text.grid(row = 0, column = 0)
# Stop button
self.stop = tkinter.ttk.Button(self.root, text = "Stop", command = lambda: self.close())
self.stop.grid(row = 1, column = 1, columnspan = 2)
while self.running:
for word in self.getWords():
self.text.after(FastReader.SLEEP_TIME)
self.text.config(text = word)
self.text.update_idletasks()
self.root.update_idletasks()
self.root.mainloop()
def close(self):
self.running = False
def getFile(self):
file_ = tkinter.filedialog.askopenfilename()
return file_
def getWords(self):
with open(self.filename) as file_:
for line in file_:
for word in line.strip("\n").split(" "):
yield word
if __name__ == "__main__":
fr = FastReader()
fr.window()
答案 0 :(得分:2)
您的程序似乎挂起,因为您在事件循环有机会更新显示之前处理所有单词,然后您在无限循环中调用事件循环。
一个好的经验法则是永远不要在Tkinter GUI中拥有自己的无限循环。你已经有一个无限循环运行,所以利用它。
你应该做的是编写一个函数,将下一个单词放在标签中,然后再调用自己。它看起来有点递归,但它并不完全。您只是在事件循环必须执行的事情列表中添加一些内容。因为它不是严格递归的,所以你不必担心堆栈空间不足。
简单的第一步是首先一次读入所有单词。然后,程序将删除列表中的第一个单词并将其显示在标签中。如果此后列表不为空,请将命令安排在延迟后再次运行。它看起来像这样:
def showNextWord(self):
word = self.words.pop(0)
self.text.configure(text=word)
if len(self.words) > 0:
self.root.after(self.SLEEP_TIME, self.showNextWord)
然后,您可以使用两个语句替换while语句:一个用于获取完整的单词列表,另一个用于显示第一个单词:
self.words = self.getWords()
self.showNextWord()
当然,您需要修改getWords()
以立即返回整个列表。你可以使用一个生成器,但它增加了一点似乎不必要的复杂性,除非你计划显示数百万个单词(每秒四次,运行时间超过几天)。