I have a problem in implementing a fast reader program with tkinter, and that is because it hangs after ~5 seconds.
I know that is because of the while loop but I didn't figured out a way to solve it. Maybe looping outside of the root mainloop?
Here is the code:
SLEEP_TIME = 250
self.filename = self.getFile()
self.running = True
self.root = tkinter.Tk()
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)
for word in self.getWords():
self.text.config(text = word)
self.running = False
file_ = tkinter.filedialog.askopenfilename()
with open(self.filename) as file_:
for line in file_:
for word in line.strip("\n").split(" "):
if __name__ == "__main__":
fr = FastReader()
Best How To :
Your program appears to hang because you process all of the words before you give the event loop a chance to update the display, then you put a call to the event loop in an infinite loop.
A good rule of thumb is to never have your own infinite loop in a Tkinter GUI. You already have an infinite loop running, so take advantage of it.
What you should do is write a function that puts the next word in the label, and then calls itself again in the future. It looks somewhat recursive, but it isn't quite. You're simply adding something on to the list of things that the event loop must do. Because it's not strictly recursive, you don't have to worry about running out of stack space.
A simple first step is to first read in all of the words at once. Then, your program removes the first word in the list and displays it in the label. If the list is not empty after that, schedule the command to run again after a delay. It looks something like this:
word = self.words.pop(0)
if len(self.words) > 0:
You can then replace your while statement with two statements: one to get the complete list of words, and one to display the first word:
self.words = self.getWords()
Of course, you need to modify your
getWords() to return the whole list at once. You can use a generator, but it adds a tiny bit of complexity that doesn't seem necessary, unless you're planning on displaying millions of words (which, at four per second, would run for more than several days).