Я работаю над созданием секундомера с двумя значениями. Он начинается со значения A и отсчитывается до 0, затем изменяется на значение B, отсчитывается до 0, затем возвращается к значению A, отсчитывается до 0 и т.д., пока я не закрою программу (я, вероятно, добавлю кнопку паузы в некоторых точка) и в целом работает очень хорошо. Однако, когда он обновляет метку новым текстом, кажется, что он просто создает новый текстовый элемент и помещает его как слой поверх предыдущего. Тогда я могу видеть, что когда я перехожу от однозначного двузначного числа к однозначному, а предложение сокращается, часть старого предложения, которая не охвачена, все еще видна. Так что я надеюсь, что мне просто не хватает чего-то невероятно простого. Я думал, что newWindow.update() обновит окно, но похоже, что он этого не делает. Ниже мой фрагмент кода, который обрабатывает логику.

    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)
0
jon 25 Фев 2021 в 00:32

2 ответа

Лучший ответ

Вы создаете новый виджет Label каждый раз в цикле while вместо изменения текста внутри цикла while. Вот почему он накладывает один виджет поверх другого, поэтому вам нужно создать свой виджет, затем запустить цикл while и настроить текст для изменения в timer.config внутри цикла. Вы также должны объявить шрифт в исходном tk.Label, нет необходимости изменять его при каждом прохождении цикла. Для "some_starting value", вероятно, будет "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)
1
skytale 24 Фев 2021 в 22:02

Из вашего кода сложно сказать, где это происходит, но обычно это делается вот как:

  • Сделайте метку вне всех функций в основном блоке.
timer = tk.Label(newWindow,font=("TkDefaultFont",30)) # Adding the font here itself
  • Теперь внутри функции просто измените ее значение, используя 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)

Итак, теперь каждый раз, когда выполняется функция / цикл, новые метки не будут создаваться и перезаписываться, вместо этого будет настроена существующая метка.


Кстати, использование цикла time.sleep() и while - не лучшая практика, даже с update() это все равно вызовет какие-то нарушения в графическом интерфейсе. Вместо этого измените порядок кода, чтобы использовать метод after(ms,func), который не замораживает графический интерфейс. Вы можете задать новый вопрос по этому поводу, если у вас возникнут проблемы, позже.

1
Cool Cloud 24 Фев 2021 в 22:03