Tkinter can do, but remember, scheduling works in a different manner
Tkinter is a GUI-oriented framework, with a lot power built-in.
( Python per-se allows you to design things independently of Tkinter. )
Tkinter-side timer-based event(s) can be set, however as said above, user-side control of timer is avoided ( no reasonable near-real-time system will allow user to de-stabilise, the less to block, the flow of code-execution ... )
So. The Tkinter scheduling tools are basically these:
aTkScheduledEVENTid = <aTkRootWidget>.after( msecsAfter, aFun2Bcalled = None, *args )
# use
# for deterministic / set wait-time
aTkDeferredEVENTid = <aTkRootWidget>.after_idle( aFun2Bcalled = None, *args )
# use
# for non-deterministic / deferred till <SIG_IDLE> state of the GUI control-loop
<aTkRootWidget>.after_cancel( { aTkScheduledEVENTid | aTkDeferredEVENTid } )
# use
# upon a need to **cancel**/re-schedule a set execution
The solo-call magic
A scheduled function call is executed only once, so it is rather common to repeat the scheduling task again "inside" the called function, to re-instate the registration for a next timer-based function call.
Arthur has posted above a link to a neat, Bryan Oakley's, code-snippet.
Adding a trick can help you read the real plasticity of the Tkinter timing under real load.
( Some platforms do not show time-resolution under [msec]-s )
class App(): # Bryan Oakley, in http://stackoverflow.com/a/2401181/3666197
def __init__( self ):
self.root = tk.Tk()
self.label = tk.Label( text = "init" )
self.label.pack()
self.update_clock() # inital call to set a scheduled execution
self.root.lower() # OP.Edit: hide the Tk-window, as wanted
self.root.mainloop()
def update_clock( self ):
# \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
#
# DEMO to show real plasticity of the Tkinter scheduler timing(s)
#
print time.time() # show real activation timestamp w [msecs]
#
# /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
now = time.strftime( "%H:%M:%S" )
self.label.configure( text = now )
self.root.after( 1000, # re-instate next scheduled call, theoretically after given delay
self.update_clock
)