Как создать таймер обратного отсчета, который продолжает отсчет после однократного нажатия кнопки, обновляя текст на холсте tkinter

Я пытаюсь создать окно tkinter, в котором у меня есть таймер обратного отсчета и кнопка. Как только я нажимаю кнопку, я хочу, чтобы таймер непрерывно отсчитывал время. Текст в окне также должен отсчитывать каждую секунду, пока не достигнет 0:00.

До сих пор я использовал этот код. Я пробовал time.sleep() и window.after(), чтобы попытаться рассчитать время, но все мое окно tkinter показывает либо 2:00, прежде чем я нажму кнопку, либо 0:00 через секунду.


def countdown():
    total_seconds = 60
    total_minutes = 2

    while total_seconds != 0:
        if total_seconds == 60:
            total_seconds -= 1
            total_minutes -= 1
            time.sleep(1)
            canvas.itemconfig(timer_text, text=f"{total_minutes}:{total_seconds}")
        elif total_seconds == 1 and total_minutes != 0:
            total_seconds += 59
            time.sleep(1)
            canvas.itemconfig(timer_text, text=f"{total_minutes}:00")
        elif total_seconds == 0 and total_minutes > 0:
            total_seconds = 59
            total_minutes -= 1
            time.sleep(1)
            canvas.itemconfig(timer_text, text=f"{total_minutes}:{total_seconds}")
        elif total_seconds < 10:
            total_seconds -= 1
            time.sleep(1)
            canvas.itemconfig(timer_text, text=f"{total_minutes}:0{total_seconds}")
        else:
            total_seconds -= 1
            time.sleep(1)
            canvas.itemconfig(timer_text, text=f"{total_minutes}:{total_seconds}")

window = Tk()
window.title("Title comes here")
window.config(padx=100, pady=50, bg=BLUE)



canvas = Canvas(width=400, height=450, bg=BLUE, highlightthickness=0)
timer_text = canvas.create_text(210, 100, text = "2:00", fill = "white", font=(FONT_NAME, 35, "bold"))
canvas.grid(column=1, row=1)


start_button = Button(text = "Start", command=countdown)
start_button.grid(column=0, row=2)


При запуске вашего кода (после добавления window.mainloop()) и нажатии кнопки Start приложение зависает, а текст меняется на «0:00» через 2 минуты, а не одну секунду. Не рекомендуется использовать цикл while в приложении tkinter. Либо запустите цикл while в потоке, либо используйте вместо него .after().

acw1668 21.11.2022 03:51
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
1
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот решение без цикла while и реализовано after как предложено. Ваши условия для обновления времени уже были очень хорошими.

import tkinter as tk
import time


def countdown(total_seconds=60, total_minutes=2):
    if total_seconds == 60:
        total_seconds -= 1
        total_minutes -= 1
        timer_text.config(text=f"{total_minutes}:{total_seconds}")
        window.after(1000, countdown, total_seconds, total_minutes)        
    elif total_seconds == 1 and total_minutes != 0:
        total_seconds += 59
        timer_text.config(text=f"{total_minutes}:00")
        window.after(1000, countdown, total_seconds, total_minutes)        
    elif total_seconds == 0 and total_minutes > 0:
        total_seconds = 59
        total_minutes -= 1
        timer_text.config(text=f"{total_minutes}:{total_seconds}")
        window.after(1000, countdown, total_seconds, total_minutes)        
    elif total_seconds < 11 and total_seconds > 0:
        total_seconds -= 1
        timer_text.config(text=f"{total_minutes}:0{total_seconds}")
        window.after(1000, countdown, total_seconds, total_minutes)   
    elif total_seconds == 0 and total_minutes == 0:
        pass
    else:
        total_seconds -= 1
        timer_text.config(text=f"{total_minutes}:{total_seconds}")
        window.after(1000, countdown, total_seconds, total_minutes)        


window = tk.Tk()
window.title("Title comes here")
window.config(padx=100, pady=50, bg='BLUE')

timer_text = tk.Label(window, text = "TIMER", font=('Arial', 35, "bold"), bg='blue')
timer_text.grid(column=1, row=1)

start_button = tk.Button(text = "Start", command=countdown)
start_button.grid(column=0, row=2)

window.mainloop()

Не рекомендуется использовать цикл while в приложении tkinter, вместо этого используйте .after().

Ниже приведен модифицированный countdown() с использованием .after():

def countdown(seconds=120):
    mins, secs = divmod(seconds, 60)
    canvas.itemconfig(timer_text, text=f"{mins}:{secs:02}")
    if seconds > 0:
        canvas.after(1000, countdown, seconds-1)

Другие вопросы по теме