简体   繁体   中英

How to make a count down timer on button when triggered

So Im trying to create a count down timer in the form of mm:ss and start counting down in an interval of 1 second when the button is being pressed. Im trying to make the timer show on the button too when counting down. This is what I have so far and I'm not sure what to do.

import tkinter as tk
root = tk.Tk()
monsterTimer = '00:02'
def converter(sec):
    m, s = map(int, sec.split(":"))
    sec = m * 60 + s
    sec -= 1
    m, s = divmod(sec, 60)
    sec = (f'{m:02d}:{s:02d}')
    if sec != '00:00':
        sec = 'end'
    root.after(1000, converter)
    return sec

def update_btn_text():
    btn_text.set(converter(monsterTimer))

btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: update_btn_text())
btn.place(x=10, y=10)
root.mainloop()

Your solution was close, and using after instead of threads is the right way to go.

The first problem is that when you use root.after , you are calling converter but you aren't passing in an argument. You need to change the line to look like the following, which will call converter(sec) every second.

root.after(1000, converter, sec)

Another problem you have is that you are setting set to 'end' if it is not 00:00. You need to set it only if it is 00:00:

if sec == '00:00':
    sec = 'end'

Third, you need to update the button text inside of converter , sometime before calling after :

...
btn_text.set(sec)
root.after(1000, converter, sec)

Finally, you don't need update_btn at all. It can be removed, and you can call converter from your button command.

btn = tk.Button(root, textvariable=btn_text, command=lambda: converter(monsterTimer))

Putting it all together, it looks like this:

import tkinter as tk
root = tk.Tk()
monsterTimer = '00:10'
def converter(sec):
    m, s = map(int, sec.split(":"))
    sec = m * 60 + s
    sec -= 1
    m, s = divmod(sec, 60)
    sec = (f'{m:02d}:{s:02d}')
    if sec == '00:00':
        sec = 'end'
    btn_text.set(sec)
    if sec != "end":
        root.after(1000, converter, sec)

btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: converter(monsterTimer))
btn.place(x=10, y=10)
root.mainloop()

Try this code:

import tkinter as tk
import time
import threading

root = tk.Tk()
monsterTimer = '00:00'
run_tm = 5


def update_btn_text(sec):
    while sec:
        m, s = divmod(sec, 60)
        m, s = str(m).zfill(2), str(s).zfill(2)
        tm = f'{m}:{s}'
        btn_text.set(tm)
        time.sleep(1)
        sec -= 1
    btn_text.set("00:00")


def startThread(t):
    th1 = threading.Thread(target=update_btn_text, args=(t, ))
    th1.start()


btn_text = tk.StringVar()
btn_text.set(monsterTimer)
btn = tk.Button(root, textvariable=btn_text, command=lambda: startThread(run_tm))
btn.place(x=50, y=50)
root.mainloop()

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