Create a main loop with tkinter?

I have this code:

from tkinter import *

root = Tk()
while True:
    print('hello')
    root.update()

root.mainloop()

And here the main loop is:

while True:
    print('hello')
    root.update()

But I'm not sure thats the best way to do that (this doesn't work if i want to input something)

Then i tried this one:

from tkinter import *
from threading imoport Thread
import time

root = Tk()

text = Label()
text.pack()

def main():
    while True:
        text[text] = str(time.time())

thread = Thread(target=main)
thread.start()

root.mainloop()

But as i've realised that doesn't work as fast as i expected. So the question is: Whats the best way to create a main loop?


Tkinter provide a powerfull tool for it and it is called after. It is intended as synchronous sleep command but can build a loop inside the mainloop by calling itself.

after , a built-in Tcl command, manages the scheduling of scripts for future evaluation, and also functions as a synchronous sleep command.

import tkinter as tk #import tkinter
import datetime #import datetime for our clock

def tick(): #function to update the clock
    showed_time = clock['text'] #current showed time
    current_time = datetime.datetime.now().strftime("%H:%M:%S") #real time
    if showed_time != current_time: #if the showed time is not the real time
        showed_time = current_time #update the variable to compare it next time again
        clock.configure(text=current_time) #update the label with the current time
    clock.after(1000, tick) #call yourself in 1000ms (1sec.) again to update the clock
    return None

root=tk.Tk()

clock = tk.Label(root)
clock.pack()
tick()

root.mainloop()

In the above script we had built a digital clock and get in touch with the after method. The after method is nothing but an interval and on the end of that interval we want that something happen.

To learn more about this basic widget method [click]

after(delay_ms, callback=None, args)

This method registers a callback function that will be called after a given number of milliseconds. Tkinter only guarantees that the callback will not be called earlier than that; if the system is busy, the actual delay may be much longer.

import tkinter as tk 
import datetime 

def tick():
    showed_time = clock['text']
    current_time = datetime.datetime.now().strftime("%H:%M:%S")
    if showed_time != current_time:
        showed_time = current_time
        clock.configure(text=current_time)
    global alarm #make sure the alarm is known
    alarm = clock.after(1000, tick)#assign the alarm to a variable
    return None
def stop():
    stop.after_cancel(alarm) #cancel alarm
    

root=tk.Tk()

clock = tk.Label(root)
clock.pack()
stop = tk.Button(root, text='Stop it!', command=stop)
stop.pack()
tick()


root.mainloop()

Here we have the same code but with the ability to cancel our loop with the after_cancel method of tkinter. You dont need to global the alarm inside a class. self.alarm = self.clock.after(...) works fine.

after_cancel(id)

Cancels an alarm callback.

id

Alarm identifier.

Why threading isn't a good choice in coding frame work.