tkinter clearing canvas and starting a new "task" problem

Thread Starter

zazas321

Joined Nov 29, 2015
936
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 :

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)
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:
Code:
master = tk.Tk()
app = Application(master=master)
app.Create_canvas(1920,1080)
app.Application_Intro()
app.mainloop()
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:
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")
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:
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)
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
 
Top