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