Presentation on Different ways to create time delay in tkinter
Short Video (about 35sec)
Python code Text
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 16 11:41:30 2023
@author: aleja
Analog Meter GUI and Demo for learning
"""
from tkinter import *
#for some reason from tkinter.ttk import * cause bg lightblue error
#from tkinter.ttk import Combobox
#import math
import time
#import datetime
#import os #for path filename join
import threading
#GUI setup below
myWindow=Tk()
myWindow.title("myWindow-Tkinter and TimeDelay GUI")
w_w=850
w_h=400
myWindow.minsize(w_w,w_h)
#myWindow.maxsize(w_w,w_h) #if you want to move the operator table to see rest of belt comment out
#next time use resize=false,false
# do this or frame (last frame row number, in window will not follow window (expanding)
myWindow.grid_rowconfigure(1,weight=1) #Important This was the reason for on frame being stuck at bottom was row 0 but 3frames
myWindow.grid_columnconfigure(1,weight=1)
myWindow.configure(background='gray')
#***FRAMES buttons
# adjust r,c,sticky, row and column config as need
frame1=Frame(myWindow,width=130,height=300,bg='lightblue')
frame1.grid(row=0, column=0, sticky='NS', padx=10, pady=10, columnspan=1,rowspan=4)
frame1.rowconfigure(0,weight=1)
frame1.rowconfigure(1,weight=1)
frame1.rowconfigure(2,weight=1)
frame1.rowconfigure(3,weight=1)
frame1.columnconfigure(0,weight=1) #the lastcol goes along with rigth side expanding
#frame2 Right
# adjust r,c,sticky, row and column config as need
frame2=Frame(myWindow,width=300,height=300,bg='blue')
frame2.grid(row=1, column=1, sticky='NESW', padx=(0,10), pady=(0,10), columnspan=1,rowspan=4) #padding ALSO takes two arguments tuple
frame2.rowconfigure(0,weight=1)
frame2.rowconfigure(1,weight=1)
frame2.rowconfigure(2,weight=1)
frame2.columnconfigure(1,weight=1) #the lastcol goes along with rigth side expanding
#Top frame
frame3=Frame(myWindow,width=100,height=100,bg='lightblue')
frame3.grid(row=0, column=1, sticky='NESW', padx=(0,10), pady=10, columnspan=2) #padding ALSO takes two arguments tuple
frame3.rowconfigure(1,weight=0)
frame3.columnconfigure(1,weight=1) #the lastcol goes along with rigth side expanding
#frame3 info
AppTitleLabel=Label(frame3, width=40,text=" Time Delay methods Display ")
CompanyName=Label(frame3, text="YourCompanyName")
AppTitleLabel.grid(row=0, column=0, padx=0, pady=10, columnspan=2) #span 2 so it does not affect component button
CompanyName.grid(row=0, column=3, padx=10, sticky='E') #Keep
#place to put time
Time_Label1=Label(frame2,height=2,text="Put time Here",font=('Arial',20,''))
Time_Label1.grid(row=0, column=0, padx=10, pady=10, columnspan=2,sticky='WE') #span 2 so it does not affect component button
Label.config(Time_Label1,text="")
#place to put time
Time_Label3=Label(frame2,height=2,text="Put time Here",font=('Arial',20,''))
Time_Label3.grid(row=1, column=0, padx=10, pady=10, columnspan=2,sticky='WE') #span 2 so it does not affect component button
Label.config(Time_Label3,text="")
Time_Label4=Label(frame2,height=2,text="Put time Here",font=('Arial',20,''))
Time_Label4.grid(row=2, column=0, padx=10, pady=10, columnspan=2,sticky='WE') #span 2 so it does not affect component button
Label.config(Time_Label4,text="")
Label_List=[Time_Label3,Time_Label4]
def GetTime():
TimeNow=time.time()
delay_sec=2
time.sleep(delay_sec) #this is blocking type function in tkinter main thread so remember avoid
TimeAfter=time.time()
#TimeNow_datetime=datetime.datetime.now()
#Label.config(Time_Label,text=TimeNow) # time from some long ago time ref still good for delta
#Label.config(Time_Label,text="Date Time factional time: "+str(TimeNow_datetime))
#Label.config(Time_Label,text="Time format: "+str(TimeNow_datetime.strftime("%H:%M:%S")))
#Label.config(Time_Label,text="Date m/d/Y format: "+str(TimeNow_datetime.strftime("%m/%d/%Y")))#
deltaTime=TimeAfter-TimeNow
Label.config(Time_Label1,text=str(delay_sec)+"sec delay: "+str(deltaTime))
#thread starter
def GetTime_w_Thread():
threading.Thread(target=GetTime, daemon=True).start() #important WITHOUT the () on the function otherwise it blocks
print("threading notice same function that had time.sleep but not in tkinter thread,its own")
#Two Parts The Thread and a non-Thread checker
#Testing non-Thread and Thread call to this functino
Done_Flag=[0,0] #two thread use
def GetTime2(StartingTime=None,Which_Label=0,delay_sec_arg=0.0):
global Label_List
global Done_Flag
global Button_List
print(Which_Label)
#(Button_List[Which_Label])['state']='disabled' #I do see that a large time.sleep in thread
#can still affect button state from changing quickly even if time.sleep is after the button state
#many have stated to not have tkinter type call in thread so need to work that
myWindow.update
delay_sec=delay_sec_arg
TimeNow=time.time()
time.sleep(0.001) #this is used to testout if function is "really" running "move GUI test" thread base , adjust to make thread slow or fast to see is_alive affect
#the very first thread run is ok but since 'after' is calling not thread it blockable again (move the gui after press)
deltaTime=TimeNow-StartingTime
Label.config(Label_List[Which_Label],text=str(delay_sec)+"sec delay: " + str("{:0.3F}".format(deltaTime)))
if(deltaTime>=delay_sec):
Label.config(Label_List[Which_Label],text=str(delay_sec)+"sec delay: " + str("{:0.3F}".format(deltaTime))) #remember the : infront of format number
Done_Flag[Which_Label]=1
Button_List[Which_Label]['state']='normal'
#Done do it here if(Done_Flag[Which_Label]==0):myWindow.after(100,lambda:GetTime2(StartingTime,Which_Label,delay_sec)) #to low a after time WILL overload CPU time
return
#non-thread checker
def Start_Checking_The_Thread(TD,StartingTime,Which_Label,delay_sec_arg):
global Done_Flag
print(TD.is_alive())
if(TD.is_alive()):
print("Thread is still alive") #if the threaded function is slow you will see alive more offen
else:
print("Thread is done") # if the thread function is quick you will be done more offen
if(Done_Flag[Which_Label]==0):
#NO this was not really running a thread TD=threading.Thread(target=GetTime2(StartingTime,Which_Label,delay_sec_arg), daemon=True)
TD=threading.Thread(target=GetTime2,args=(StartingTime,Which_Label,delay_sec_arg,), daemon=True) #important no () on target function
TD.start()
TD.is_alive()
# if you make after to small it will comsume CPU percent - just know this d- alway how slow can i go still be ok with app (100ms can give +/-100ms error to time)
myWindow.after(50,lambda:Start_Checking_The_Thread(TD,StartingTime,Which_Label,delay_sec_arg)) #to0 low an after time WILL overload CPU time
#too low a ms after time WILL overload CPU time and tkinter thread , need to find a balance that works for your app
#with 50ms: accuracy +codetime0+/-50ms not absolute since on Windows you are not the only app(aka NOT Realtime computer)
#check with the task manager(windows) to see if cpu using to to high if it is you need to increase the after time
else:
print("done checking") #to0 low an after time WILL overload CPU time
return
#thread starter button event
def GetTime_w_Thread2(Which_Label=0,delay_sec_arg=0.0):
global Label_List
global Button_List
global Done_Flag
Done_Flag[Which_Label]=0
global StartingTime
(Button_List[Which_Label])['state']='disabled'
StartingTime=time.time()
print(StartingTime)
#in "this" particle case both non-thread and thread working "Simalarly" but not the same (non-Thread can be blocked)
#GetTime2(StartingTime,Which_Label,delay_sec_arg) #this works but NOT Threading
TD=threading.Thread(target=GetTime2(StartingTime,Which_Label,delay_sec_arg), daemon=True)
TD=threading.Thread(target=GetTime2,args=(StartingTime,Which_Label,delay_sec_arg,), daemon=True)
TD.start()
print("Thread",TD.is_alive())
#threading.Thread(target=GetTime2,args=(StartingTime,Which_Label,delay_sec_arg), daemon=True).start()
Start_Checking_The_Thread(TD,StartingTime,Which_Label,delay_sec_arg)
print("Thread",TD.is_alive())
b_width=20
GetTime_Btn=Button(frame1, text='GetDelta with \n time.sleep delay 2sec \n freeze tk GUI for \n that time',\
width=b_width, command=lambda:GetTime())
GetTime_Btn.grid(row=0, column=0,padx=10,pady=10)
GetTime_Btn=Button(frame1, text='GetDelta with \n time.sleep delay 2sec\n and thread \n does NOT freeze tk GUI for \n that time',\
width=b_width, command=lambda:GetTime_w_Thread())
GetTime_Btn.grid(row=1, column=0,padx=10,pady=10)
StartTime=time.time()
GetTime2_Btn=Button(frame1, text='GetDelta with 2s\n "after" \n and thread',width=b_width, command=lambda:GetTime_w_Thread2(0,2.0))
GetTime2_Btn.grid(row=2, column=0,padx=10,pady=10)
GetTime3_Btn=Button(frame1, text='GetDelta2 with 3s \n "after \n and thread',width=b_width, command=lambda:GetTime_w_Thread2(1,3.0))
GetTime3_Btn.grid(row=3, column=0,padx=10,pady=10)
Button_List=[GetTime2_Btn,GetTime3_Btn]
#main Window GUI looping
myWindow.mainloop()
Python code download
Notes
- Presentation: Python Learn Tkinter and time delay examples
- Programming Language used: Python 3.7 in Spyder
- Presentation app: Microsoft’s PowerPoint
- Python and Tkinter are products of respective company
- Lots of Help and credit to “Stackoverflow” ,product of respective company
- Presentation shown to spark ideas of use.
- This presentation is not connected to or endorsed by any company.
- Use at your own risk.
- Tags: Python, Python3.7, Tkinter, GUI, List, Thread ,Tkinter and Timedelay, TimeDelay, After function, Python Learn Tkinter and time delay examples