Search code examples
pythonfunctiontkinterpause

How can I use a single button to pause and unpause timer in tkinter? (without using pygame)


I'm working on a simple timer that counts down 30 mins for me to study and 5 mins for a break. So far, the start_timer function and count_down function work well, I just cannot figure out how to write the pause function. I did some research for a few days. Most articles are using pygame or to bind with different keys. I am wondering what function I should use for one tkinter button to pause/unpause my timer if something comes up and I want to pause the timer till I'm back.

Thank you @TimRoberts, I can pause the timer now. However, I don't know how to unpause the timer to let it continue counting down.

My timer looks like this

from tkinter import *
import math
WORK_MIN = 30
BREAK_MIN = 5
reps = 0
paused = False
# --------------------------- TIMER  ---------------------------- #
def start_timer():
    global reps
    reps += 1
    work_sec = WORK_MIN * 60
    break_sec = BREAK_MIN * 60
    if reps % 2 == 1:
        title_label.config(text="Study")
        count_down(work_sec)
    else:
        title_label.config(text="Break")
        count_down(break_sec)
    window.attributes('-topmost', 0)


# ------------------------ COUNTDOWN--------------------------- #
def count_down(count):
    global paused
    count_min = math.floor(count / 60)
    count_sec = count % 60
    if count_min < 10:
        count_min = f"0{count_min}"
    if count_sec < 10:
        count_sec = f"0{count_sec}"
    canvas.itemconfig(timer_text, text=f"{count_min}:{count_sec}" )
    if count > 0:
        if not paused:
            count -= 1
            window.after(1000, count_down, count-1)
    else:
        start_timer()
# ---------------------------- PAUSE ------------------------------- #

def pause_function():
    global paused
    paused = not paused

# ---------------------------- UI ------------------------------- #
window = Tk()

title_label = Label(text="Timer")
title_label.grid(column=1, row=0)
check_marks = Label(text="")
check_marks.grid(column=1, row=4)

canvas = Canvas(width=200, height=224, bg="lightblue")
timer_text = canvas.create_text(100, 128, text="00:00", fill="white", font=("Courier", 45, "bold"))
canvas.grid(column=1, row=1)

start_button = Button(text="Start", command=start_timer)
start_button.grid(column=0, row=2)
pause_button = Button(text="Pause", command=pause_function)
pause_button.grid(column=2, row=2)

window.mainloop()

Solution

  • You need to do the "after" call even if you're paused, otherwise you'll never notice when you unpause. Also, since you're decrementing count once, you don't need to do it again:

    def count_down(count):
        count_min = count // 60
        count_sec = count % 60
        canvas.itemconfig(timer_text, text=f"{count_min:02d}:{count_sec:02d}" )
        if count:
            if not paused:
                count -= 1
            window.after(1000, count_down, count)
        else:
            start_timer()
    

    If you want to be tricky, you could use:

        if count:
            count -= not paused
    

    since True is 1 and False is 0.