0

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()
Cynthia168
  • 28
  • 5
  • 2
    Well, the `pause_function` just needs to be `paused = not paused`. Then, whatever is doing the countdown, which you have not showed us, would check that flag when deciding whether to count down or not. – Tim Roberts Oct 17 '22 at 20:35
  • 1
    First you need to define a function that does what you would like, then you need to call that function and in that function you call the same function with after. After returns an identifier that you can cancel. [See this answer](https://stackoverflow.com/questions/63118430/create-a-main-loop-with-tkinter/63118515#63118515) for instance. – Thingamabobs Oct 17 '22 at 20:37
  • 1
    So, in your `count > 0` branch, you just do `if not paused:` / `count -= 1` then pass `count` to `window.after`. You don't need to save the result of the `window.after`, and you don't need `global reps`. – Tim Roberts Oct 18 '22 at 00:12
  • Hi @TimRoberts, thank you for replying. I tried to be precise and didn't know it can be relevant. I showed all my codes now, can you show me how to write the pause function? – Cynthia168 Oct 18 '22 at 00:12
  • Hi @Thingamabobs, thank you for replying and for the link. After I read it, I still don't know what to do. – Cynthia168 Oct 18 '22 at 00:14
  • I already SHOWED you how to write the pause function. That was my very first comment. Did you not believe me? – Tim Roberts Oct 18 '22 at 00:19
  • @TimRoberts. Like this? `if count > 0:` `if not paused:` `count -= 1` `window.after(1000, count_down, count-1)` `def pause_function():` `paused = not paused ` <-I got an error - unresolved reference 'paused' I can't pause my timer so far. Tim, it's nothing about I don't believe you. I'm a beginner and I don't know which part of the code was wrong so it doesn't work. – Cynthia168 Oct 18 '22 at 00:46
  • See [ask]. You need to post a [mre] and debugging details. Also see [Rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging). If you understand your own code(```start_timer()``` and ```count_down()```), you should be able to implement to pause and resume. – relent95 Oct 18 '22 at 02:48

1 Answers1

1

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.

Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • Thank you for the answer. My timer works great. I'm curious about why `if count > 0:` can simplify to `if count:` ? And the last part is because pause= false(0) so `not pause` =True(1). That blows my mind! I learned Python could not do arithmetic operations between different data types. – Cynthia168 Oct 19 '22 at 04:57
  • 1
    That's totally untrue. You can add floats and ints, and True and False are really just other names for 1 and 0. Every Python type has the notion of "truthiness": an empty list, string, dict or set are False, as is the integer 0. So, `if count:` is short for `if count is not 0:`. – Tim Roberts Oct 19 '22 at 05:52
  • That's really interesting. Thank you, Tim. I've learned a lot from you. Although it's not long, there are many ways of writing code I've learned from the answer. – Cynthia168 Oct 20 '22 at 05:03