Hello. I am using python tkinter to create interface for my application. I have made a very bad spaghetti code initially and managed to get it to work without using the mainloop. I would like to improve my previous code and get my program to work properly with tkinter mainloop.
I have created an application class :
i use some global variables inside my class because I have other functions outside the class that access to those variables.
my main code starts like that:
As you can see from the function above, i am calling Application_intro function which is handles my main GUI. One of the GUI widgets is the "new operation" button:
After pressing that button, the code executed is:
As you can see from the code above, the function deletes all previous canvas elements and calls new Application_intro. I just want to delete whatever happened during the previous task and start a fresh task.
The issue is:
I can see that canvas.delete("all") properly deletes all canvas widgets and Application_Intro code is being called to generate a new widgets HOWEVER, it does not seem to start a "fresh" task. It continues to execute the code that is not supposed to.
For example, if I am in the middle of a task:
The code below is my task:
I am not gonna go into details about what this code does, but it waits for me to "initiate" the next pick. When this task is started, it prints me the message ("wait for next command"). When I execute new_operation() which supposed to clear canvas and start a fresh task, it continues to print "wait for next command"
In short, I want to be able to press a button which would clear whole GUI, and and basically start a "new" tkinter GUI. But my current function does not stop the current mainloop even though it clears canvas and creates a new instance of Application_intro
I have created an application class :
Code:
class Application(tk.Frame):
flag_ota_button = 0
def __init__(self,master=None):
super().__init__(master)
self.master = master
def Create_canvas(self,canvas_width,canvas_height):
global canvas
canvas = tk.Canvas(self.master,bg='ivory2',width=canvas_width,height=canvas_height)
def Application_Intro(self):
print("starting new app")
global label_RED
global entry_input# define this as global so it can be read in the callback function
#canvas = tk.Canvas(self.master,bg='ivory2',width=canvas_width,height=canvas_height)
label1 = tk.Label(canvas,text = "SKENUOKITE BARKODA(GUID) ARBA DAIKTO RIVILINI KODA:",font='Helvetica 16 bold',bg='ivory2',foreground="red")
entry_input = tk.Entry(canvas) # entry = guid
entry_input.focus_set()
end_program_button = tk.Button(canvas, text="Baigti",font='Helvetica 12 bold', width=20, height=2, command=self.end_program)
restart_program_button = tk.Button(canvas, text="Restartuoti",font='Helvetica 12 bold', width=20, height=2, command =self.Restart)
ota_button = tk.Button(canvas, text="Atnaujinti",font='Helvetica 12 bold', width=20, height=2, command=self.OTA_gui)
remove_item_button = tk.Button(canvas, text="Isvalyti dezute",font='Helvetica 12 bold', width=20, height=2, command=self.Remove_item_gui)
new_operation_button = tk.Button(canvas, text="Nauja operacija",font='Helvetica 12 bold', width=20, height=2, command = self.New_operation)
canvas.create_text(960,20,text="PICK TO LIGHT",font='Helvetica 16 bold')
label_RED = canvas.create_window(960,75,window=label1)
self.user_input_entry=canvas.create_window(960,125,window=entry_input)
canvas.create_window(1210,200,window=ota_button)
canvas.create_window(960,200,window=remove_item_button)
canvas.create_window(710,200,window = new_operation_button)
canvas.create_window(1210,400,window = end_program_button)
canvas.create_window(710,400,window = restart_program_button)
entry_input.bind('<Return>',read_user_input)
canvas.pack()
def picking_gui(self):
self.devices = {}
device_list,serial_list = count_unique_devices(myConnection)
print("the list of devices=",device_list)
img_red_original = Image.open("camera_red.png")
img_red_original = img_red_original.resize((50,50),Image.ANTIALIAS)
self.img_red = ImageTk.PhotoImage(img_red_original)
img_green_original = Image.open("camera_green.png")
img_green_original = img_green_original.resize((50,50),Image.ANTIALIAS)
self.img_green = ImageTk.PhotoImage(img_green_original)
red_image = canvas.create_image(100,50,image=self.img_red,anchor='nw')
self.update_RED_label(label_RED,960,75,"Imkite daiktus is nurodytu dezuciu")
gaminio_kodas_text = "Gaminio kodas="+user_input
gaminio_serial_text = "Serial="+komplektacijos_Serial
gaminio_IMEI_Text = "IMEI="+komplektacijos_Imei
canvas.create_text(960,400,text=gaminio_kodas_text,font='Helvetica 12 bold')
canvas.create_text(960,425,text=gaminio_serial_text,font='Helvetica 12 bold')
canvas.create_text(960,450,text=gaminio_IMEI_Text,font='Helvetica 12 bold')
for x in range(0,len(device_list)):
self.devices[device_list[x]] = canvas.create_rectangle(20+(x*110),550,110+(x*110),640,fill='red')
canvas.create_text(65+(x*110),585,text=device_list[x],font='Helvetica 12 bold',fill="yellow")
canvas.create_text(65+(x*110),605,text=serial_list[x],font='Helvetica 10 bold',fill="yellow")
if(x>15):
self.devices[device_list[x]] = canvas.create_rectangle(20+(x*110),650,110+(x*110),740,fill='red')
canvas.create_text(55+(x*90),585,text=device_list[x],font='Helvetica 12 bold',fill="yellow")
canvas.create_text(65+(x*110),605,text=serial_list[x],font='Helvetica 10 bold',fill="yellow")
canvas.pack()
def update_rectangle_color_initial(self,device_name):
canvas.itemconfig(self.devices[device_name],fill="green")
self.last_device = device_name
def update_rectangle_color_last(self):
canvas.itemconfig(self.devices[self.last_device],fill="red")
def update_rectangle_color(self,device_name):
canvas.itemconfig(self.devices[self.last_device],fill="red")
canvas.itemconfig(self.devices[device_name],fill="green")
self.last_device = device_name
def refresh_app(self,delay):
#refresh_variables()
canvas.delete("all")
app.after(delay,lambda:self.Application_Intro())
def update_MAIN_label(self,label,x,y,text1):
global label_MAIN
canvas.delete(label_MAIN)
label_MAIN = canvas.create_text(x,y,text=text1,font="Helvetica 14 bold")
def update_RED_label(self,label,x,y,text1):
global label_RED
canvas.delete(label_RED)
label_RED = canvas.create_text(x,y,text=text1,fill="red",font='Helvetica 16 bold')
def make_new_textbox(self,text_input):
global label_RED
global new_textbox_entry
canvas.delete(label_RED)
canvas.delete(self.user_input_entry)
label=tk.Label(canvas,text = text_input,bg='ivory2',foreground="red",font='Helvetica 16 bold')
new_textbox_entry = tk.Entry(canvas)
new_textbox_entry.focus_set()
label_RED = canvas.create_window(960,75,window=label)
self.user_input_entry = canvas.create_window(960,125,window=new_textbox_entry)
new_textbox_entry.bind('<Return>',read_user_new_textbox)
def end_program(self):
print("end program")
def Restart(self):
print("restart")
restart_devices(myConnection,"RESTART")
self.refresh_app(1000)
def OTA_gui(self):
print("OTA gui")
def Remove_item_gui(self):
print("remove item gui")
def New_operation(self):
print("new_operation")
restart_devices(myConnection,"reset")
canvas.delete("all")
app.after(1000,self.Application_Intro)
print("new operation end")
def OTA_gui(self):
self.devices = []
if(self.flag_ota_button % 2 != 0):
canvas.delete(ota_label)
canvas.delete(ota_choices)
canvas.delete(ota_button)
self.flag_ota_button+=1
return
else:
self.devices = ["device1","device2","device3","device4","device5","device6","device7","device8","device9"]
device_list,serial_list = count_unique_devices(myConnection)#get list of unique device names from MYSQL DB
print("device list OTA=",device_list)
print("sertial list OTA=",serial_list)
label = tk.Label(canvas,text="Pasirinkti kuria dezute atnaujinti",font='Helvetica 12 bold')
choices = ttk.Combobox(canvas,values=self.devices)
choices.current(0)
button = tk.Button(canvas,text="Patvirtinti",command =lambda: self.device_confirmed(choices,"ota"))
self.ota_label = canvas.create_window(960,250,window=label)
self.ota_choices = canvas.create_window(960,300,window=choices)
self.ota_button = canvas.create_window(960,350,window=button)
self.flag_ota_button+=1
def device_confirmed(self,choices,status):
device = choices.get()
if(status == "ota"):
print("device=",device)
mqttc.publish(device+"/status","OTA")
canvas.delete(self.ota_label)
canvas.delete(self.ota_choices)
canvas.delete(self.ota_button)
else:
publish_mqtt_json_item_inside("",device,"","")
canvas.delete(remove_item_label)
canvas.delete(remove_item_choices)
canvas.delete(remove_item_button)
remove_item_from_device(myConnection,device)
my main code starts like that:
Code:
master = tk.Tk()
app = Application(master=master)
app.Create_canvas(1920,1080)
app.Application_Intro()
app.mainloop()
After pressing that button, the code executed is:
Code:
def New_operation(self):
print("new_operation")
restart_devices(myConnection,"reset")
canvas.delete("all")
app.after(1000,self.Application_Intro)
print("new operation end")
The issue is:
I can see that canvas.delete("all") properly deletes all canvas widgets and Application_Intro code is being called to generate a new widgets HOWEVER, it does not seem to start a "fresh" task. It continues to execute the code that is not supposed to.
For example, if I am in the middle of a task:
The code below is my task:
Code:
def handle_next_pick():
print("handling next pick")
global item_number
global flag_next_device
print("pick counter =",pick_counter)
if(pick_counter < Counter_global):
if(flag_next_device>0):
print("flag_next_device is higher than 1")
if(item_number > 0):#only check if it divides by counter if its higher then 0 to avoid glitch
if(item_number % Counter_global_temp==0):
item_number=item_number-(Counter_global_temp)
app.update_rectangle_color(Device_global_temp[item_number])
string = Device_global_temp[item_number]+"/"+"status"
mqttc.publish(string,"ACTIVE",1)
flag_next_device=0
if(update_DB==1):
update_DB_Quantity(myConnection)
else:
print("Dont need to update DB")
app.after(100,handle_next_pick)
else:
app.after(100,handle_next_pick)
print("wait for next command")
else:
app.after(1000,handle_end_of_picking)
In short, I want to be able to press a button which would clear whole GUI, and and basically start a "new" tkinter GUI. But my current function does not stop the current mainloop even though it clears canvas and creates a new instance of Application_intro