When to use the after method; faking while without threading
As mentioned in a comment, In far most cases, you do not need threading to run a "fake" while loop. You can use the after()
method to schedule your actions, using tkinter
's mainloop
as a "coat rack" to schedule things, pretty much exactly like you would in a while loop.
This works in all situations where you can simply throw out commands with e.g. subprocess.Popen()
, update widgets, show messages etc.
It does not work when the scheduled process takes a lot of time, running inside the mainloop. Therefore time.sleep()
is a bummer; it will simply hold the mainloop
.
How it works
Within that limitation however, you can run complicated tasks, schedule actions even set break
(-equivalent) conditions.
Simply create a function, initiate it with window.after(0, <function>)
. Inside the function, (re-) schedule the function with window.after(<time_in_milliseconds>, <function>)
.
To apply a break- like condition, simply rout the process (inside the function) not to be scheduled again.
An example
This is best illustrated with a simplified example:



from tkinter import *
import time
class TestWhile:
def __init__(self):
self.window = Tk()
shape = Canvas(width=200, height=0).grid(column=0, row=0)
self.showtext = Label(text="Wait and see...")
self.showtext.grid(column=0, row=1)
fakebutton = Button(
text="Useless button"
)
fakebutton.grid(column=0, row=2)
# initiate fake while
self.window.after(0, self.fakewhile)
self.cycles = 0
self.window.minsize(width=200, height=50)
self.window.title("Test 123(4)")
self.window.mainloop()
def fakewhile(self):
# You can schedule anything in here
if self.cycles == 5:
self.showtext.configure(text="Five seconds passed")
elif self.cycles == 10:
self.showtext.configure(text="Ten seconds passed...")
elif self.cycles == 15:
self.showtext.configure(text="I quit...")
"""
If the fake while loop should only run a limited number of times,
add a counter
"""
self.cycles = self.cycles+1
"""
Since we do not use while, break will not work, but simply
"routing" the loop to not being scheduled is equivalent to "break":
"""
if self.cycles <= 15:
self.window.after(1000, self.fakewhile)
else:
# start over again
self.cycles = 0
self.window.after(1000, self.fakewhile)
# or: fakebreak, in that case, uncomment below and comment out the
# two lines above
# pass
TestWhile()
In the example above, we run a scheduled process for fifteen seconds. While the loop runs, several simple tasks are performed, in time, by the function fakewhile()
.
After these fivteen seconds, we can start over again or "break". Just uncomment the indicated section to see...