简体   繁体   中英

How to properly update tkinter label element

I'm working on creating a stopwatch that is given two values. It starts with value A and counts down to 0, then changes to value B, counts down to 0, then goes back to value A, counts down to 0 etc until I close the program (I'll probably add a pause button at some point) and overall it's working really well. However, when it updates the label with the new text, It seems to just be making a new text item and putting it as a layer on top of the previous. I can see then when I go from a single double-digit number to a single digit, and the sentence is shortened, the part of the old sentence that isn't covered can still be seen. So I'm hoping I'm just missing something incredibly simple. The newWindow.update() is what I thought would update the window but it does not appear to be doing that. Below is my snippet of code that handles the logic.

    def countdown(timer_count,count_type):
        counter = timer_count
        count_type = count_type
        while counter >= 0:
            timer = tk.Label(newWindow, text=f"{count_type} for: {counter}")
            timer.config(font=("TkDefaultFont",30))
            timer.grid(row=0,column=2)
            newWindow.update()
            time.sleep(1)
            counter -= 1
            print(counter)
        if count_type == "work":
            count_type = "rest"
        elif count_type == "rest":
            count_type = "work"
        return count_type


    def interval():
        counter_type = "work"
        while True:
            if counter_type == "work":
                counter_type = countdown(int(exer_var.get()),counter_type)
            elif counter_type == "rest":
                counter_type = countdown(int(rest_var.get()),counter_type)

You are creating a new Label widget each time through your while loop instead of changing the text inside the while loop. That is why it is layering one widget on top of the other, so you need to create your widget, then run the while loop, and set the text to change in the timer.config inside the loop. You should also declare the font in the original tk.Label , no need to change that each trip through the loop. For "some_starting value" it would probably be text = counter

timer = tk.Label(newWindow, font=("TkDefaultFont",30), text="some_starting_value")
    while counter >= 0:
        timer.config(text=f"{count_type} for: {counter}")
        timer.grid(row=0,column=2)

Its hard to say from your code where this is taking place, but here is how its usually done:

  • Make the label outside all functions in the main block.
timer = tk.Label(newWindow,font=("TkDefaultFont",30)) # Adding the font here itself
  • Then now inside the function just change its value using config :
def countdown(timer_count,count_type):
    counter = timer_count
    count_type = count_type
    while counter >= 0:
        timer.config(text=f"{count_type} for: {counter}") # Update the options for the created label.
        timer.grid(row=0,column=2)

So now each time function/loop is running, new labels wont be created and overwritten, instead existing label will be configured.


On a side note, using time.sleep() and while loop is not the very best practice, even with update() it will still cause some kind of disturbance to GUI. Instead, re-arrange your code to use after(ms,func) method, which will not freeze the GUI. You can ask a new question on that if you face any trouble, later.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM