You have really two options:
A loop that runs once per 5 (or x) minutes to add to the schedule
Or scheduling the function to run again x minutes after it last finished.
In either case, your cancel
Button would just set a flag somewhere that the running function(s) should check as their first operation.
The biggest downside with the first case is that it will lock up the execution of your other code. The simpler route is definitely to make the function schedule itself after it runs. If your other code is taking a long time, threading is definitely an option you could investigate; I've not had to use it myself, but something similar to the code below should work:
import threading
import tkinter
import time
class RepeatExecute(object):
def __init__(self,master,t=2000):
self.master=master
self.time=t
def go(self):
self.GO = True
self.call_self()
def call_self(self):
if self.GO is True:
t = self.time
print(time.time())
thrd = threading.Thread(target=self.slow_execute)
thrd.start()
self.master.after(t,self.call_self)
def set_time(self,t):
self.time=t
def stop(self):
self.GO = False
def slow_execute(self):
time.sleep(1.0)
if self.GO is True:
print('Halfway')
def active(self):
print('Active')
if __name__=='__main__':
root =tkinter.Tk()
RE = RepeatExecute(root,t=2000)
btn1 = tkinter.Button(root,text='Start',command=RE.go)
btn1.grid()
btn2 = tkinter.Button(root,text='Stop',command=RE.stop)
btn2.grid()
btn3 = tkinter.Button(root,text='ACTIVE!',command=RE.active)
btn3.grid()
root.mainloop()
So hit 'Start', and it will print the time every two seconds, plus the other function will run in between. You can hit 'ACTIVE' at any time to prove the interface is responsive. I hope this is helpful? If you're really against the function calling itself, you could probably start a thread that just runs an infinite loop adding events to the queue, but this seems an unnecessary complication.
I do note that threading won't be the best choice if the slow_execute function is doing a lot of number crunching, threading is mainly for slow I/O due to the action of the global interpreter lock. Should be fine if you're waiting for results/communications.