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