Tkinter GUI to learn Queue, Put, Get, Empty, Full, Exception Handling
Short video about 42sec
Python Learn Queue – Code Text
# -*- coding: utf-8 -*-
#
#Date: 4/11/2023 Time 3:24 PM
#
from tkinter import *
from queue import Queue,Full,Empty
import threading as td
def Test_Q_Empty(q):
if(q.empty()):
canv1.itemconfigure(Queue_Empty_LED,fill='lightgreen')
else:
canv1.itemconfigure(Queue_Empty_LED,fill='grey')
return
def Test_Q_Full(q):
if(q.full()):
canv2.itemconfigure(Queue_Full_LED,fill='lightgreen')
else:
canv2.itemconfigure(Queue_Full_LED,fill='grey')
return
def Refresh_Label_autoscroll():
global Label_Result_List
RESULT['text']=""
for line in Label_Result_List:
RESULT['text']=RESULT['text'] + str(line)+"\n"
myWindow.update()
return
Test_Result_List=[]
#Test_Result_Dict={'TestName':"",'Measured':0,'Result':"NotTested"} Dont DO THIS or all will be the same
Num_of_Test=20
TRD={}
for i in range(Num_of_Test):
Test_Result_Dict={} #this way
Test_Result_Dict['TestName']="TestName_"+"{:02d}".format(i) #formating 2 digits
Test_Result_Dict['Measured']=i+100
Test_Result_Dict['Result']="Passed"
Test_Result_List.append(Test_Result_Dict)
print(Test_Result_Dict)
#Google promtp: print a list with carriage return in one line
#my find credit: stackoverflow "Printing list element on spearate lines in Python": (3rd Answer)
print(*Test_Result_List,sep="\n")
Label_Result_List=[]
#beginner error -- wrong way touching one will affect the other (like pointer) Label_Result_List=Test_Result_List
Label_Result_List=Test_Result_List.copy() #use copy to make a Different list
#print(Test_Result_List)
#GUI setup below
myWindow=Tk()
myWindow.title("Python-Learn_Queue_GUI")
myWindow.minsize(810,460)
# do this or frame in window will not follow window (expanding)
myWindow.grid_rowconfigure(0,weight=1) #need on row define as 1 for expanding row wise bottomframe
myWindow.grid_columnconfigure(0,weight=1)
#only one frame so 0,0 configure
#frame1
# adjust r,c,sticky, row and column config as need
frame1=Frame(myWindow,width=50,height=50,bg='lightblue')
frame1.grid(row=0, column=0, sticky='NWES', padx=10, pady=10, columnspan=1)
frame1.rowconfigure(8,weight=1) #only expand after last button
frame1.columnconfigure(5,weight=1) #the lastcol goes along with rigth side expanding
#where do you want it to exapand column5 last row
#LED info
LTRY=5 #light top right Y
LTRX=15 #light top right X
dia=20
#Label used canv text instead so its close to led
#Q_EMPTY=Label(frame1, text="Q is Empty",width=15)
#Q_EMPTY.grid(row=3, column=2, padx=10, pady=(10,0), columnspan=1,sticky='N')
#Led Indictor
canv1=Canvas(frame1,width=150, height=30, bg='lightblue', bd=1, highlightthickness=1)
canv1.grid(row=4, column=2, columnspan=1,sticky="")
Queue_Empty_LED=canv1.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia,fill='black')
Queue_Empty_Text=canv1.create_text(80,LTRX,width=100,text="Q is Empty")
#Label
#Q_FULL=Label(frame1, text="Q is Full",width=15)
#Q_FULL.grid(row=5, column=2, padx=10, pady=(10,0), columnspan=1,sticky='N')
#Led Indictor
canv2=Canvas(frame1,width=150, height=30, bg='lightblue', bd=1, highlightthickness=1)
canv2.grid(row=5, column=2, columnspan=1,sticky="")
Queue_Full_LED=canv2.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia,fill='black')
Queue_Full_Text=canv2.create_text(80,LTRX,width=100,text="Q is full")
canv3=Canvas(frame1,width=150, height=30, bg='lightblue', bd=1, highlightthickness=1)
canv3.grid(row=6, column=2, columnspan=1,sticky="")
Queue_Msg_LED=canv3.create_oval(LTRX,LTRY,LTRX+dia,LTRY+dia,fill='black')
Queue_Mag_Text=canv3.create_text(80,LTRX,width=100,text="Q Exception Handled ")
#achor and justify tricky in create text it work better without them in this case
#Label
APP_NAME=Label(frame1, text=" Testing - Queue Functions ",width=25)
APP_NAME.grid(row=0, column=0, padx=10, pady=10, columnspan=1,sticky='')
#Label
COMPANY_NAME=Label(frame1, text="testengineerresource.com",width=25)
COMPANY_NAME.grid(row=0, column=5, padx=10, pady=10, columnspan=1,sticky='E')
#Label
USERMSG=Label(frame1, text="Message Area",width=25)
USERMSG.grid(row=2, column=5, padx=10, pady=10, columnspan=1,sticky='E')
#Label
RESULT=Label(frame1, text="NoInfoYet",width=25,height=20,anchor='nw',justify='left')
RESULT.grid(row=3, column=5, padx=10, pady=10, columnspan=1,rowspan=7,sticky='NWSE')
#rowspan all rows so button not affected
#only Result Label will expand with window all directions
#Button
Q_PUT=Button(frame1, text='Q_PUT',width=15, command=lambda:frame_Button_Q_PUT("Q_PUT"))
Q_PUT.grid(row=3, column=0,padx=10,pady=10,sticky='')
Test_Index=0
def frame_Button_Q_PUT(button_text):
global Done_Flag
global Test_Index
print(button_text)
Test_Q_Full(que)
Test_Q_Empty(que)
if(Test_Index<Num_of_Test):
try:
print("Test Index: ",Test_Index)
print(Test_Result_List[Test_Index])
if(que.empty()):
Done_Flag=False
td.Thread(target=Tell_Manager_Done(que), daemon=True).start()
que.put(Test_Result_List[Test_Index],block=False) #not que.put= NO, added timeout so you can see affect but will not hang app
#que.put(Test_Result_List[Test_Index],timeout=1) #not que.put= NO, added timeout so you can see affect but will not hang app
Label_Result_List.append("Queue Add:"+str(Test_Result_List[Test_Index]))
Label_Result_List.pop(0)
Refresh_Label_autoscroll() #a way to gave a scrollable label could not find a good label end to autoscroll, almost a que by list, really should have been text with scrollbar
canv3.itemconfigure(Queue_Msg_LED,fill='gray')
Test_Index=Test_Index+1
except Full:
canv3.itemconfigure(Queue_Msg_LED,fill='red')
Label_Result_List.pop(0)
Label_Result_List.append("Queue is Full and attempted Put performed, Suggest Q_Get")
Refresh_Label_autoscroll() #
print("Handling Que Error Put on a Filled up que")
pass #continue
else:
Label_Result_List.pop(0)
Label_Result_List.append("No more Test in List")
Refresh_Label_autoscroll()
Reload_TestList['state']='normal'
Test_Q_Full(que)
Test_Q_Empty(que)
print(button_text)
return
#Button ======Q_GET
Q_GET=Button(frame1, text='Q_GET',width=15, command=lambda:frame_Button_Q_GET("Q_GET"))
Q_GET.grid(row=4, column=0,padx=10,pady=10,sticky='')
def frame_Button_Q_GET(button_text):
global Done_Flag
print(button_text)
Test_Q_Empty(que)
Test_Q_Full(que)
try:
item=que.get(block=False) #equivalent .get_nowait #see how block= false behaves, t1sec this can halt here if no que most time not desired
#item=(que.get(timeout=1)) #t1sec this can halt here if no que most time not desired
Label_Result_List.pop(0)
Label_Result_List.append("Queue Get:"+str(item))
Refresh_Label_autoscroll() #a way to gave a scrollable label could not find a good label end to autoscroll, almost a que by list, really should have been text with scrollbar
canv3.itemconfigure(Queue_Msg_LED,fill='gray')
except Empty: #credit stackoverflow:"Python Queue.Empty Exception handling" the last answer in list help me
canv3.itemconfigure(Queue_Msg_LED,fill='red')
print("Handling Que Error Get on an empty que")
Label_Result_List.pop(0)
Label_Result_List.append("Queue is Empty and attempted Get performed, Suggest Q_PUT")
Refresh_Label_autoscroll() #
#####que.task_done() # can not use in tkinter GUI
Done_Flag=True
pass #continue
Test_Q_Empty(que)
Test_Q_Full(que)
return
#Button
Q_DATA=Button(frame1, text='Q_DATA',width=15, command=lambda:frame_Button_Q_DATA("Q_DATA"))
Q_DATA.grid(row=7, column=0,padx=10,pady=10,sticky='')
def frame_Button_Q_DATA(button_text):
print(button_text)
Label_Result_List.pop(0)
Label_Result_List.append("How many item in q: "+str(que.qsize()))
Refresh_Label_autoscroll() #
for item in list(que.queue):
print("Item in Que",item)
Label_Result_List.pop(0)
Label_Result_List.append("Item in que: "+str(item))
Refresh_Label_autoscroll() #
return
#Button
Reload_TestList=Button(frame1, text='Reload_TestList',width=15, command=lambda:frame_Button_Reload_TestList("Reload Test List"))
Reload_TestList.grid(row=8, column=0,padx=10,pady=10,sticky='')
def frame_Button_Reload_TestList(button_text):
print(button_text)
global Test_Index
Test_Index=0
Reload_TestList['state']='disabled'
return
def Wait_Here():
global Done_Flag
print("Thread:Manager wait for you to finish gets", Done_Flag)
if Done_Flag:
Label_Result_List.pop(0)
Label_Result_List.append("Manager I finished reviewing my current que items, more work please")
Refresh_Label_autoscroll()
print("Told Manager I finished my current review of tests")
Done_Flag=False
else:
myWindow.after(1000,Wait_Here)
def Tell_Manager_Done(que):
global Done_Flag
print("Started thread")
#que.join() # YOU know you can not use this in a tkinter GUI
Done_Flag=False
Wait_Here()
#myWindow.update()
print("finshied a thread")
return
que=Queue(10) #max size to to start learning
USERMSG['text']="Max Size of Q=: "+str(que.maxsize)
#show starting list for put to use
RESULT['text']=""
for line in Label_Result_List:
RESULT['text']=RESULT['text'] + str(line)+"\n"
Reload_TestList['state']='disable'
Done_Flag=True #since at start empty que
#GUI main loop
myWindow.mainloop()
Download of code
Notes
- Presentation: Python Learn Queue GUI using
- 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, Queue, Canvas ,GUI, List, Dictionary, and Thread (limited scope)