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.