Python GUI Four UUT with Threading, progressbar, tab

Show a GUI tkinter using four UUT example with threading, includes progress bar and tabs.

Not a how to setup mux communication, focus in on GUI and threading

UUT 3 was made intentionally slow and to randomly fail to show threading in action

# -*- coding: utf-8 -*-
"""
Created on Wed Mar 22 16:11:42 2023

@author: aleja

4 UUT in threading with progressbar and tab with vertical scroll text obj
UUT 3 is made to be slow and random failure intentionally to show threading in action
"""

from tkinter import *
#for some reason from tkinter.ttk import * cause bg lightblue error
from tkinter.ttk import Progressbar,Notebook
import time
import random
import threading


Num_of_UUTs=4
Num_of_Chs=100
testinfo=""
function_still_running=0

def command1(mssg: str):
     #match mssg: #what is wrong with this oh it only in 3.10
        if mssg == "Reset":
         for uut_num in range(Num_of_UUTs):
           canv_Led_List[uut_num].itemconfig(Overall_Led_List[uut_num], fill='black')
        else:
             print("did you forget to make a case")
        
        print(mssg)
        return

def Overall_Led_Yellow(Num_of_UUTs):
    for uut_num in range(Num_of_UUTs):
       canv_Led_List[uut_num].itemconfig(Overall_Led_List[uut_num], fill='yellow')
    return
        
    
#test simulator (non process version)
def Run_UUT(uut_num):
    b1['state']="disabled"
    global function_still_running
    function_still_running=function_still_running+1
    Limits={}
    Limits={'low':3.7,"high":3.918} 
    Failed_Flag=0
    scrollv_text_list[uut_num+1].delete("1.0",END)
    
    for ch in range(Num_of_Chs):
            if (uut_num==2): #uut3
               meas_sim=random.randrange(3700,3920)/1000
               time.sleep(0.001) #slower mux to show threading in action , remember sleep is blocking type function will affect tkintr loop
            else:
               meas_sim=random.randrange(370,380)/100 
            print(uut_num+1,ch,meas_sim)
            #limit check  
            if Limits['low']<=meas_sim<=Limits['high']:
                print("pass")
                scrollv_text_list[uut_num+1].insert(INSERT,"ch: "+str(ch) +" measureV: "+ str(meas_sim) +" Passed"+ "\n")
                scrollv_text_list[uut_num+1].yview(END)
            else:
                print("fail*******")
                Failed_Flag=1
                scrollv_text_list[uut_num+1].insert(INSERT,"ch: "+str(ch) +" measureV: "+ str(meas_sim) +" ***Failed***" +"\n")
                scrollv_text_list[uut_num+1].yview(END)
            #time.sleep(0.001) # 1ms remove the command itsself is affecting the tk GUI thead speed
            pb.setvar(name=("PB_value" + str(uut_num+1)),value=ch) #surprized a bit , works becayse of PBs varialbe name even if last pb was not its matching pb
            myWindow.update()

    if Failed_Flag==0:
            canv_Led_List[uut_num].itemconfig(Overall_Led_List[uut_num], fill='lightgreen')
            scrollv_text_list[uut_num+1].insert(INSERT,"Passed UUT:"+str(uut_num+1) + "\n")
            scrollv_text_list[uut_num+1].yview(END)
            scrollv_text_list[0].insert(INSERT,"Passed UUT:"+str(uut_num+1) + "\n") #UUT overall
            scrollv_text_list[0].yview(END)
    else: 
        canv_Led_List[uut_num].itemconfig(Overall_Led_List[uut_num], fill='red')
        scrollv_text_list[uut_num+1].insert(INSERT,"***Failed*** UUT:"+str(uut_num+1) + "\n")
        scrollv_text_list[uut_num+1].yview(END)
        scrollv_text_list[0].insert(INSERT,"***Failed*** UUT:"+str(uut_num+1) + "\n") #UUT overall
        scrollv_text_list[0].yview(END)
        
    function_still_running=function_still_running-1
    if function_still_running<=0 :
      b1['state']="normal"
    return     

def Start_Testing():
    Overall_Led_Yellow(Num_of_UUTs)
    scrollv_text_list[0].delete("1.0",END) #UUT overall text clear from1 to end
    for uut_num in range(Num_of_UUTs):
     print(uut_num,Num_of_UUTs)
     threading.Thread(target=Run_UUT,args=(uut_num,)).start()   #create and start same line 
     #this is what finally work(Restart NEW Thread )(error should have said cannot start a "terminated" thread)
     # not use join anywhere it will not work with tk gui
    return

def tab_event_handler(event):
      tab_is=event.widget.select()
      tab_text=event.widget.tab(tab_is,"text")  #get the tabs label/text
      print(tab_text)
#===============================================================================        
#GUI setup below
myWindow=Tk()
myWindow.title("myWindow")
myWindow.minsize(425,500)

# do this or frame in window will not follow window (expanding)
#check your row config is you find that some frame are window bottom sticking instead of following NSEW
#i have three frame so row index 2 (its ok for that frame to auto grow following NWE , s by window)
myWindow.grid_rowconfigure(2,weight=1)  #Important This was the reason for  on frame being stuck at bottom was row 0 but 3frames
myWindow.grid_columnconfigure(0,weight=1)

frame1=Frame(myWindow,width=50,height=50,bg='lightblue')
frame1.grid(row=0, column=0, sticky='NWE', padx=10, pady=10, columnspan=4)
frame1.rowconfigure(0,weight=1)
frame1.columnconfigure(3,weight=1) #the lastcol goes along with rigth side expanding

L1=Label(frame1, text=" UUT Test - BatteryPack Sim",width=25)
L2=Label(frame1, text="YourCompanyName")
L1.grid(row=0, column=0, padx=10, pady=10, columnspan=3) #span 2 so it does not affect component button
L2.grid(row=0, column=3, padx=10, sticky='E') #Keep company label attached to east(right) side

b1=Button(frame1, text='Start Test', command=lambda:Start_Testing())
#b2=Button(frame1, text='Optical Test', command=lambda:printtext("button2"))
#b3=Button(frame1, text='RF Test', command=lambda:printtext("button3"))
b4=Button(frame1, text='Reset', command=lambda:command1("Reset"))

b1.grid(row=1, column=0,padx=(10,0))
#b2.grid(row=1, column=1)
#b3.grid(row=1, column=2)
b4.grid(row=1, column=3,padx=10,sticky='E') #keep Reset button on Right side


# frame 1 indictor,make some rownd ovals for LED indictors (use for in range next time)
canv1=Canvas(frame1,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv2=Canvas(frame1,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv3=Canvas(frame1,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv1.grid(row=2, column=0, padx=(10,0), columnspan=1) #padding to match first button
canv2.grid(row=2, column=1, columnspan=1)
canv3.grid(row=2, column=2, columnspan=1)

#========Frame 1 indicator=========
LTRY=5 #light top right Y
LTRX=15 #light top right X
dia=20
c1=canv1.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia,fill='black')
c2=canv2.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')
c3=canv3.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')



#frame2 row1
frame2=Frame(myWindow,width=70,height=200,bg='lightblue',)
frame2.grid(row=1,column=0,sticky="NEWS" ,columnspan=1,padx=10,pady=0) #yes pady 0 because frame1,3
frame2.rowconfigure(4,weight=1) # four progressbar 4rows
frame2.columnconfigure(1,weight=1) #this was important for the progressbar to auto grow width (column 1 autogrow)

#frame3 row2
frame3=Frame(myWindow,width=380,height=100,bg='lightblue')  #pad x y not here
frame3.grid(row=2,column=0,columnspan=1,sticky="NSEW",padx=10,pady=10)
frame3.rowconfigure(0,weight=1)
frame3.columnconfigure(0,weight=1) #this was important for the progressbar to auto grow width (column 1 autogrow)



#=======================Tab Section (frame3)==============================================
#
tab_Holder=Notebook(frame3,style='Custom.TNotebook',width=300,height=100)
tab_Holder.grid(row=0,column=0,sticky='NEWS',columnspan=1,rowspan=1,padx=20,pady=20)
tab_Holder.rowconfigure(1,weight=1)
tab_Holder.columnconfigure(1,weight=1)

# more adv way use for in range and list of tabs
# leaving flat (not adv) so you can learning mode

tab1=Frame(tab_Holder)  #tab obj to notebook but not added yet
tab1.columnconfigure(0,weight=1) #lessons learn You must thell tab object that thing inside can auto grow
tab1.rowconfigure(0,weight=1)
tab2=Frame(tab_Holder)
tab2.columnconfigure(0,weight=1)
tab2.rowconfigure(0,weight=1)
tab3=Frame(tab_Holder)
tab3.rowconfigure(0,weight=1)
tab3.columnconfigure(0,weight=1)
tab3.rowconfigure(0,weight=1)
tab4=Frame(tab_Holder)
tab4.columnconfigure(0,weight=1)
tab4.rowconfigure(0,weight=1)
tab5=Frame(tab_Holder)
tab5.columnconfigure(0,weight=1)
tab5.rowconfigure(0,weight=1)
tab_list=[tab1,tab2,tab3,tab4,tab5] # for adding scroll text obj in each tab


tab_Holder.bind("<<NotebookTabChanged>>",tab_event_handler)
tab_Holder.add(tab1,text="UUT_overall")
tab_Holder.add(tab2,text="UUT1")
tab_Holder.add(tab3,text="UUT2")
tab_Holder.add(tab4,text="UUT3")
tab_Holder.add(tab5,text="UUT4")

scrollv_text_list=[]  #now your learn List and for in 
for tab in tab_list:
    txt1=Text(tab,width=30,height=10)
    txt1.grid(row=0,column=0,columnspan=2,sticky='NWES',padx=20,pady=20)
    txt1.columnconfigure(0,weight=1)
    txt1.rowconfigure(0,weight=1)     
    #attach a Scrollbar to txt1
    vscroll=Scrollbar(tab,orient=VERTICAL,command=txt1.yview)
    txt1['yscroll']=vscroll.set
    vscroll.grid(row=0,column=1,sticky='NSE',padx=20,pady=20)
    scrollv_text_list.append(txt1)

#========================================================================



#new way
UUT_L=[Label(frame2, text=("UUT"+str(i+1))) for i in range(Num_of_UUTs)]
row_num=0
for UUT_LG in UUT_L:
    UUT_LG.grid(row=row_num, column=0, padx=2, pady=10, columnspan=1)
    row_num=row_num+1
   

#need to read up on style for pb looks more involved ,fgcolor="yellow" is no go ,thats would have been to easy
pb_list=[Progressbar(frame2, maximum=Num_of_Chs-1,length=175,orient="horizontal",value=0,variable=("PB_value"+str(i+1))) for i in range(Num_of_UUTs)]
row_num=0
for pb in pb_list:
    pb.grid(row=row_num,column=1, padx=10,pady=10,sticky='WE') ##this was important for the progressbar wiget  auto grow to column
    row_num=row_num+1


# =================use indicators use for i in range for more adv way===============================
canv1=Canvas(frame2,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv2=Canvas(frame2,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv3=Canvas(frame2,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)
canv4=Canvas(frame2,width=50, height=30, bg='lightblue', bd=0, highlightthickness=0)

canv1.grid(row=0, column=3, columnspan=1,sticky='E') #padding to match first button
canv2.grid(row=1, column=3, columnspan=1,sticky='E')
canv3.grid(row=2, column=3, columnspan=1,sticky='E')
canv4.grid(row=3, column=3, columnspan=1,sticky='E')

canv_Led_List=[canv1,canv2,canv3,canv4]

#========indicator=========
LTRY=5 #light top right Y
LTRX=15 #light top right X
dia=20
UUT1_Overall_LED=canv1.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')
UUT2_Overall_LED=canv2.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')
UUT3_Overall_LED=canv3.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')
UUT4_Overall_LED=canv4.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia, fill='black')
Overall_Led_List=[UUT1_Overall_LED,UUT2_Overall_LED,UUT3_Overall_LED,UUT4_Overall_LED]
#===============================================================




#start with button enabled=normal
b1['state']="normal"
b4['state']="normal"


#start GUI
myWindow.mainloop()

Notes

  • Presentation: example GUI Four UUT in threading, simulated measurement and result
  • Programming Language used: Python 3.7 in Spyder
  • Presentation app: Microsoft’s PowerPoint
  • 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, progressbar, tab, text , vertical scroll ,append to list, update(add to dictionary), random

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