Search code examples
pythontkintercustomtkinter

Glitching text in an updating frame in customtkinter


In my program, I have a frame (in customtkinter), this frame updates to display new information each time a button is pressed. The issue is that some of the text is glitched after pressing more than 1-2 buttons to display different things. Not sure what the issue is or how to solve it.

Heres my code:

    def linepick(linechoice):
        
        if linechoice == "Waterloo & City":
            linechoice = "waterloo-city"

        else:
            None
           
        if linechoice == "Hammersmith & City":
            linechoice = "hammersmith-city"

        else:
            None

        endpoint = f"https://api.tfl.gov.uk/Line/{linechoice}/Status"
        response = requests.get(endpoint)
        
        if response.status_code == 200:
           
           data = response.json()

           if len(data) > 0 and "lineStatuses" in data[0]:
               linedata1 = data[0]["lineStatuses"][0]
               
               if linechoice == "waterloo-city":
                linechoice = "Waterloo & City"

               else:
                None
           
               if linechoice == "hammersmith-city":
                linechoice = "Hammersmith & City"

               else:
                None

               label1 = ct.CTkLabel(frame, text=f'{linechoice} line:{linedata1["statusSeverityDescription"]}', font=("Arial", 16))
               label1.place(x=0, y=30)
        
        elif response.status_code == 300:

            redirection = response.headers["location"]
            rerequest = requests.get(redirection)
            rerequestdata = rerequest.json()

            if len(rerequestdata) > 0 and "lineStatuses" in rerequestdata[0]:
                linedata2 = rerequestdata[0]["lineStauses"][0]

                if linechoice == "waterloo-city":
                 linechoice = "Waterloo & City"

                else:
                 None
           
                if linechoice == "hammersmith-city":
                  linechoice = "Hammersmith & City"

                else:
                 None

                label2 = ct.CTkLabel(frame, text=f'{linechoice} line:{linedata2["statusSeverityDescription"]}', font=("Arial", 16))
                label2.place(x=0, y=30)

        else:
           label3 = ct.CTkLabel(frame, text="Status line not reached, try again later.", font=("Arial", 16))
           label3.place(x=0, y=30)
        
    
    #Creating an optionmenu---------------------------------------
    stationmenu = ct.CTkOptionMenu(
        issuewindow, 
        values=["Bakerloo","Waterloo & City","Central","Circle","District","Hammersmith & City","Jubilee","Metropolitan","Northern","Piccadilly","Victoria"], 
        font=("Arial", 20), 
        corner_radius=10,
        fg_color="#0C56FF",
        command=linepick)
    stationmenu.place(x=35, y=40)

Thats the function which updates the text and thats the option menu im using

The frame itself is just a simple frame in tkinter.

Heres a picture of the glitching:

Picture of the glitching.

I think one way of solving it would be to make the frame update itself each time a button is pressed but i'm not sure how to really implement that in here. (my programming skills are very basic)


Solution

  • The problem is you are creating new labels without deleting the old ones. The way it is set up now also does not have a reference to the old labels to delete them.

    The easiest thing to do to fix this is to create the label outside the function and just update the label's text instead of creating a new label. to do this you can just create your label like when creating your stationmenu you can see an example of this below...

    # create optionmenu
    stationmenu = ct.CTkOptionMenu(
        issuewindow, 
        values=["Bakerloo","Waterloo & City","Central","Circle","District","Hammersmith & City","Jubilee","Metropolitan","Northern","Piccadilly","Victoria"], 
        font=("Arial", 20), 
        corner_radius=10,
        fg_color="#0C56FF",
        command=linepick
    )
    stationmenu.place(x=35, y=40)
    
    # create optionmenu label
    stationmenu_label = ct.CTkLabel(frame, text="", font=("Arial", 16))
    stationmenu_label.place(x=0, y=30)
    

    You might just need to specify the starting text of the label. Then when an option is selected in your stationmenu then you just change the text of the label and update the window. A cleaned-up example of this is shown below.

    def linepick(linechoice):
        url_encoded_linechoice = linechoice
        
        if url_encoded_linechoice == "Waterloo & City":
            url_encoded_linechoice = "waterloo-city"  
        elif url_encoded_linechoice == "Hammersmith & City":
            url_encoded_linechoice = "hammersmith-city"
    
        endpoint = f"https://api.tfl.gov.uk/Line/{url_encoded_linechoice}/Status"
        response = requests.get(endpoint)
        data = None
        text = "" #specify default text if 'lineStatuses' is not in the data
        
        if response.status_code == 200:
           data = response.json()
    
           if len(data) > 0 and "lineStatuses" in data[0]:
               linedata = data[0]["lineStatuses"][0]
               text = f'{linechoice} line:{linedata["statusSeverityDescription"]}'
        
        elif response.status_code == 300:
            redirection = response.headers["location"]
            rerequest = requests.get(redirection)
            data = rerequest.json()
            
            if len(data) > 0 and "lineStatuses" in data[0]:
                linedata = data[0]["lineStauses"][0]
                text= f'{linechoice} line:{linedata["statusSeverityDescription"]}' 
    
        else:
           text = "Status line not reached, try again later."
        
        stationmenu_label["text"] = text # or instead you can use stationmenu_label.configure(text = text)
        # update your window using your_window_name.update()
        # update your window's idletasks using your_window_name.update_idletasks() 
    

    This code was not tested so it may need slight tweaking to fit your needs, but it should fix the problems you were having with the label.