I think you need thread and queue...let me show a little demo.
I've set time.sleep(1) per seconds in the thead class.
In this matter you get two advantages, first repet your funcion any times
you desire and second your program never freeze it self.
import tkinter as tk
import threading
import queue
import datetime
import time
class MyThread(threading.Thread):
def __init__(self, queue,):
threading.Thread.__init__(self)
self.queue = queue
self.check = True
def stop(self):
self.check = False
def run(self):
while self.check:
x = "Doing stuff.. "
y = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
msg = x+y
time.sleep(1)
self.queue.put(msg)
class App(tk.Frame):
def __init__(self,):
super().__init__()
self.master.title("Hello World")
self.master.protocol("WM_DELETE_WINDOW",self.on_close)
self.queue = queue.Queue()
self.my_thread = None
self.init_ui()
def init_ui(self):
self.f = tk.Frame()
w = tk.Frame()
tk.Button(w, text="Start", command=self.launch_thread).pack()
tk.Button(w, text="Stop", command=self.stop_thread).pack()
tk.Button(w, text="Close", command=self.on_close).pack()
w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
def launch_thread(self):
if (threading.active_count()!=0):
self.my_thread = MyThread(self.queue)
self.my_thread.start()
self.periodiccall()
def stop_thread(self):
if(threading.active_count()!=1):
self.my_thread.stop()
def periodiccall(self):
self.checkqueue()
if self.my_thread.is_alive():
self.after(1, self.periodiccall)
else:
pass
def checkqueue(self):
while self.queue.qsize():
try:
ret = self.queue.get(0)
msg = "%s"%(ret)
print(msg)
except queue.Empty:
pass
def on_close(self):
if(threading.active_count()!=1):
self.my_thread.stop()
self.master.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()