Python tkinter and time delay

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

About LV_TS_Test_Engineer_3000_VI

Automated Test Equipment Software
This entry was posted in Test Sector and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s