python GUI countdown timer (don't use classes) - python

i have just one problem in my source code, lbl_time will not change, all thing running well except this.
I could only use function in my program, if someone can help me in this functional program, please do it.
import tkinter as tk
from datetime import timedelta
import winsound
set time is a function that for counting down time, i use timedelta for building a time object to simple operation
def main():
def set_time(hours:int=0, minutes:int=0, seconds:int=0):
end = timedelta(hours=hours, minutes=minutes, seconds=seconds)
one_second = timedelta(seconds=1)
result = end - one_second
new_time = seconds_to_hms(result.seconds)
if result.seconds is 0:
while True:
try:
winsound.PlaySound("Ringtones\\1.cookie clock.wav", winsound.SND_FILENAME)
except KeyboardInterrupt:
break
else:
hours, minutes, seconds = new_time.get('hours'), new_time.get('minutes'), new_time.get('seconds')
time.set(str(hours)+':'+str(minutes)+':'+str(seconds))
root.update()
root.after(1000, lambda : set_time(hours, minutes, seconds))
def seconds_to_hms(seconds:int) -> dict:
hours, minutes, seconds = 0, 0, seconds
if seconds >= 3600:
hours = seconds//3600
seconds = seconds - hours*3600
if seconds >= 60:
minutes = seconds//60
seconds = seconds - minutes*60
result = {'hours': hours, 'minutes': minutes, 'seconds': seconds}
return result
def quit(*args):
root.destroy()
root = tk.Tk()
root.title(string='Timer')
time = tk.StringVar()
root.configure(background='black')
logo = tk.PhotoImage(file='Logo.png')
lbl_logo = tk.Label(root, image=logo, bg='black').pack(side='right')
lbl_timer = tk.Label(root, padx=10, text="Timer", fg='white', bg='black', font='Times 24', anchor='center').pack()
lbl_time = tk.Label(root, text=time, font="Times 38", fg='white', bg='black').pack()
btn_start = tk.Button(root, text='start', bg='gray', fg='black', command=lambda : set_time()).pack()
root.bind('x', quit)
root.after(1000, lambda : set_time(0,0, 3))
root.mainloop()
if __name__ == '__main__':
main()

Took some time to understand your question, but I might have solved your problem.
Fundamentally you ought to have used textvariable rather than text as an argument in your lbl_time declaration.
If your while loop is executed, it might result in an infinite loop, you might want to have an increment if the code branches there.
Do check out the following, you might want to uncomment some of the lines, hopefully it does solve your problem:
import tkinter as tk
from datetime import timedelta
import winsound
def main():
def set_time(hours:int=0, minutes:int=0, seconds:int=0):
end = timedelta(hours=hours, minutes=minutes, seconds=seconds)
one_second = timedelta(seconds=1)
result = end - one_second
new_time = seconds_to_hms(result.seconds)
if result.seconds is 0:
while True:
try:
winsound.PlaySound("Ringtones\\1.cookie clock.wav", winsound.SND_FILENAME)
except KeyboardInterrupt:
break
else:
hours, minutes, seconds = new_time.get('hours'), new_time.get('minutes'), new_time.get('seconds')
time.set(str(hours)+':'+str(minutes)+':'+str(seconds))
root.update()
root.after(1000, lambda : set_time(hours, minutes, seconds))
def seconds_to_hms(seconds:int) -> dict:
hours, minutes, seconds = 0, 0, seconds
if seconds >= 3600:
hours = seconds//3600
seconds = seconds - hours*3600
if seconds >= 60:
minutes = seconds//60
seconds = seconds - minutes*60
result = {'hours': hours, 'minutes': minutes, 'seconds': seconds}
return result
def quit(*args):
root.destroy()
root = tk.Tk()
root.title(string='Timer')
time = tk.StringVar()
root.configure(background='black')
# logo = tk.PhotoImage(file='Logo.png')
# lbl_logo = tk.Label(root, image=logo, bg='black').pack(side='right')
lbl_timer = tk.Label(root, padx=10, text="Timer", fg='white', bg='black', font='Times 24', anchor='center').pack()
lbl_time = tk.Label(root, textvariable=time, font="Times 38", fg='white', bg='black').pack() #changed text to textvariable
btn_start = tk.Button(root, text='start', bg='gray', fg='black', command=lambda :set_time(0,0,3700)).pack()
root.bind('x', quit)
#root.after(1000, lambda : set_time(0,0, 3))
root.mainloop()
if __name__ == '__main__':
main()

Related

How to create mutliple child windows from tkinter root window?

I am new to python and learning tkinter apps. I am trying to build an app that can spawn multiple instances of countdown timer and run them separately. I have been able to create a template code and can run one child window successfully but when I open another child window first one pauses and only the last one runs.
MWE
How to make all the child window countdown timers run separately?
Problem: If I click Scripts menu, then the countdown pauses itself.
%%writefile a.py
import time
import tkinter as tk
from tkinter import ttk,messagebox
def countdown(win):
child = tk.Toplevel(win)
child.geometry('400x300')
child.resizable(0, 0)
def _show_current_clock_time(label):
str_clock_time = time.strftime('%H:%M:%S %p')
label.config(text=str_clock_time)
label.after(1000, lambda: _show_current_clock_time(label))
def _countdown(child,v_hrs,v_mins,v_secs,int_secs):
if int_secs is not None:
total_seconds = int_secs
else:
total_seconds = int(v_hrs.get()) * 3600 + int(v_mins.get()) * 60 + int(v_secs.get())
while total_seconds > -1:
minute, second = (total_seconds // 60, total_seconds % 60)
hour = 0
if minute > 60:
hour, minute = (minute // 60, minute % 60)
v_secs.set(second);v_mins.set(minute);v_hrs.set(hour)
child.update();time.sleep(1)
if (total_seconds == 0):
messagebox.showinfo('Times Up!')
v_secs.set('00');v_mins.set('00');v_hrs.set('00')
total_seconds -= 1
tk.Label(child,text='Countdown Clock and Timer').pack()
tk.Label(child, font='arial 15 bold', text='current time :').place(x=40, y=70)
# label: current time body
l_curr_time = tk.Label(child)
l_curr_time.place(x=190, y=70)
_show_current_clock_time(l_curr_time)
# variables: secs mins hrs
v_secs = tk.StringVar()
e_secs = tk.Entry(child, textvariable=v_secs, width=2, font='arial 12')
e_secs.place(x=250, y=155)
v_secs.set('00')
v_mins = tk.StringVar()
e_mins = tk.Entry(child, textvariable=v_mins, width=2, font='arial 12')
e_mins.place(x=225, y=155)
v_mins.set('00')
v_hrs = tk.StringVar()
e_hrs = tk.Entry(child, textvariable=v_hrs, width=2, font='arial 12')
e_hrs.place(x=200, y=155)
v_hrs.set('00')
# label: set the time
tk.Label(child, font='arial 15 bold', text='set the time',bg='papaya whip').place(x=40, y=150)
# button: start
x,w = 0,40
tk.Button(child,text='Run',bd='1',
command= lambda x=[child,v_hrs,v_mins,v_secs,None]: _countdown(x[0],x[1],x[2],x[3],x[4])).place(x=280, y=150)
for i,minn in enumerate([1,2,3,4]):
tk.Button(child,text=str(minn)+'m',
command= lambda x=[child,v_hrs,v_mins,v_secs,minn*60]: _countdown(
x[0],x[1],x[2],x[3],x[4]),).place(x=x+w*i, y=200)
win = tk.Tk()
menubar = tk.Menu(win)
menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Scripts", menu=menu)
menu.add_command(label='Countdown',command=lambda : countdown(win))
menu.add_command(label='Countdown 2',command=lambda : countdown(win))
menu.add_command(label='Countdown 3',command=lambda : countdown(win))
win.config(menu=menubar)
win.mainloop()

Call a fonction from message box Tkinter

I want to call the fonction (submit) after clicking on the message box. With this code I have to reclick on button everytime after the messagebox but would appreciate if the timer launch automatically after clicking on the message box.
If anyone have a clue I will appreciate.
The following code :
import time
from tkinter import *
root = Tk()
root.resizable(width=False, height=False)
root.geometry("300x250")
root['background']='#39E5F9'
root.title("Time To Drink Water")
minute = StringVar()
second = StringVar()
minute.set("45")
second.set("00")
minuteEntry = Entry(root, width=3, font=("Arial", 35, ""),
textvariable=minute,justify='center')
minuteEntry.place(x=50, y=60)
secondEntry = Entry(root, width=3, font=("Arial", 35, ""),
textvariable=second,justify='center')
secondEntry.place(x=170, y=60)
def submit():
# stored in here : 2700 = 45 mins
temp = 2700
while temp > -1:
# divmod(firstvalue = temp//60, secondvalue = temp%60)
mins, secs = divmod(temp, 60)
if mins > 60:
hours, mins = divmod(mins, 60)
minute.set("{0:2d}".format(mins))
second.set("{0:2d}".format(secs))
root.update()
time.sleep(1)
if (temp == 0):
messagebox.showinfo("Time Countdown", "Time To Drink !")
temp -= 1
def go():
btn = Button(root, text='Goodbye dehydration!', bd='6',
command=submit)
btn.place(x=90, y=160)
go()
root.mainloop()
messagebox is waiting for your click so you can run submit() after messagebox and it will run it after clicking in messagebox
But you shouldn't use while and sleep because it may freeze GUI (in any framework, and in any language). You can use root.after(1000, function) to run function again after 1000ms (1s) and it will work as sleep and while together.
import time
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
# --- functions --- # PEP8: all functions before main code
def submit():
update_counter(2700)
def update_counter(temp):
if temp > -1: # `if` instead of `while` because `after` will work as loop
# divmod(firstvalue = temp//60, secondvalue = temp%60)
mins, secs = divmod(temp, 60)
if mins > 60:
hours, mins = divmod(mins, 60)
minute.set("{:02d}".format(mins)) # use `:02` to get `09` instead of ` 9` (with space)
second.set("{:02d}".format(secs))
temp -= 1
root.after(1000, update_counter, temp) # run again after 1000ms
else:
messagebox.showinfo("Time Countdown", "Time To Drink !")
root.after(0, update_counter, 2700) # run again after 0ms
#update_counter(2700) # run again
# --- main --- # PEP8: `lower_case_names` for variables
running = False
temp = 2700
root = tk.Tk()
minute = tk.StringVar(root)
second = tk.StringVar(root)
minute.set("45")
second.set("00")
minute_entry = tk.Entry(root, width=3, textvariable=minute, font=("Arial", 35, ""), justify='center')
minute_entry.grid(row=0, column=0)
second_entry = tk.Entry(root, width=3, textvariable=second, font=("Arial", 35, ""), justify='center')
second_entry.grid(row=0, column=1)
btn = tk.Button(root, text='Goodbye dehydration!', command=submit)
btn.grid(row=1, column=0, columnspan=2)
root.mainloop()
PEP 8 -- Style Guide for Python Code
There is other problem. You can click button two times and it will run two update_counter() at the same time. It may need to disable button, or you would have to use boolean variable - ie. running = False - to control if it has to run update_counter() or not.

Tkinter .after() method going faster than it should

I been working on a simple Tkinter Gui in which a timer gets involved. The thing is that the timer goes faster than the milliseconds specified in the .after() method. Here is my code:
import tkinter
import time
from tkinter import *
seconds = 604800
FONT = ("Arial", 24)
window = tkinter.Tk()
window.attributes('-topmost', True)
window.attributes('-fullscreen', True)
window.title("Sandbox Crypto")
window.configure(bg='red')
seconds = 604800
def gui():
text = StringVar()
def substract_seconds():
global seconds
seconds -=1
while seconds > 0:
mins, secs = divmod(seconds, 60)
hours, mins = divmod(mins, 60)
days, hours = divmod(hours, 24)
timer = '{:02d}:{:02d}:{:02d}:{:02d}'.format(days,hours,mins, secs)
text.set(timer)
Time_label = Label(window, textvariable=text, bg='red', fg='white', font=FONT)
Time_label.grid()
Time_label.place(x=10, y=300)
Time_label.update()
Time_label.after(1000, substract_seconds)
window.mainloop()
gui()
The strange thing here is that i investigated the .after() method common errors and most of them were related to the method actually going slower than it should. One of my theories is that is an error related to the CPU speed because the speed of the clock varies through the time. What I infer from this is that sometimes it goes faster and then it slows down and continue going faster.
Since you used while loop, there is new scheduled task created to update the seconds in every iteration.
You don't need the while loop at all, below is modified gui():
def gui():
text = StringVar()
Time_label = Label(window, textvariable=text, bg='red', fg='white', font=FONT)
Time_label.place(x=10, y=300)
def countdown(seconds=seconds):
mins, secs = divmod(seconds, 60)
hours, mins = divmod(mins, 60)
days, hours = divmod(hours, 24)
timer = '{:02d}:{:02d}:{:02d}:{:02d}'.format(days,hours,mins, secs)
text.set(timer)
if seconds > 0:
Time_label.after(1000, countdown, seconds-1)
countdown() # start the count down
window.mainloop()

Alternative for while loops in tkinter

I am trying to make an alarm application: the alarm should go off at a pre-set time. The piece of code I have works completely fine without tkinter, but with tkinter it doesn't work at all.
In the original piece of code there is a while loop and I've noticed and read that that can't be combined with tkinter. I decided to get rid of the loop, but now the alarm goes off immediately when I enter a time.
I've read about using r.after(time_ms, function()). But I don't know how to implement that properly in my code. I've read that it has to be at the end of the function and before r.mainloop(), but I couldn't get it to work. Can somebody please help me? Thank you very much!
I've read a lot or stackoverflow posts about this, but I am not experienced enough to get it to work with those answers. :(
import tkinter as tk
from datetime import datetime, date
import time
from pygame import mixer
r = tk.Tk()
r.title('Smart Watch')
def alarm_sound():
mixer.init()
mixer.music.load('Wecker-sound.mp3')
def end():
mixer.init()
mixer.music.stop()
def display_output():
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
confirmation_message = ('Alarm has been set for ' + hour + ':' +
minute + ':' + second + '.')
text_label['text'] = confirmation_message
if (time.localtime().tm_hour == hour and
time.localtime().tm_min == entry_minute.get() and
time.localtime().tm_sec == entry_second.get()):
alarm_sound()
mixer.music.play()
message = tk.Label(r, text='What is the alarm message you\'d like to receive when the alarm goes off?',
font=('Roboto-regular', 12), fg='black')
message.pack()
entry_message = tk.Entry(r, width=45)
entry_message.pack()
enter_hour = tk.Label(r, text='Enter the hour for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_hour.pack()
entry_hour = tk.Entry(r, width=10)
entry_hour.pack()
enter_minute = tk.Label(r, text='Enter the minute for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_minute.pack()
entry_minute = tk.Entry(r, width=10)
entry_minute.pack()
enter_second = tk.Label(r, text='Enter the second for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_second.pack()
entry_second = tk.Entry(r, width=10)
entry_second.pack()
text_label = tk.Label(r, font=('Roboto-regular', 12, 'bold'),
fg='tomato')
text_label.pack()
submit_button = tk.Button(r, text='Submit',
fg='black', width=30, height=2, relief='groove',
cursor='hand2', command=display_output)
submit_button.pack()
snooze_button = tk.Button(r, text='Snooze alarm',
fg='black',
width=30, height=2, relief='groove',
cursor='hand2', command=end)
snooze_button.pack()
r.mainloop()
# The original code without tkinter has the while loop like this:
while True:
if time.localtime().tm_hour == hr and time.localtime().tm_min == mn and time.localtime().tm_sec == sc:
print(message)
break
alarm_Sound()
mixer.music.play()
First you should use global variables to keep values from Entry and use them later in function which check time. This function should use after to run its again when there is no time for alarm. It should also skip after() to stop checking time.
def display_output():
global int_hour
global int_minute
global int_second
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
text_label['text'] = 'Alarm has been set for {}:{}:{}.'.format(hour, minute, second)
# start checking time
check_time()
def check_time():
dt = time.localtime()
if (dt.tm_hour == int_hour and dt.tm_min == int_minute and dt.tm_sec == int_second):
alarm_sound()
mixer.music.play()
else:
r.after(1000, check_time) # check it again after 1000ms but only if it doesn't play sound
Code would need other global variables to control if alarm in running when you stop it and when you try to set it again.
import time
from datetime import datetime, date
import tkinter as tk
from pygame import mixer
# --- functions ---
def alarm_sound():
global running_alarm
running_alarm = True
mixer.music.load('Wecker-sound.mp3')
def end():
global running_alarm
if running_alarm:
running_alarm = False
mixer.music.stop()
text_label['text'] = ''
def display_output():
global int_hour
global int_minute
global int_second
hour = entry_hour.get()
int_hour = int(hour)
minute = entry_minute.get()
int_minute = int(minute)
second = entry_second.get()
int_second = int(second)
confirmation_message = ('Alarm has been set for {}:{}:{}.'.format(hour, minute, second))
text_label['text'] = confirmation_message
check_time()
def check_time():
dt = time.localtime()
if (dt.tm_hour == int_hour and dt.tm_min == int_minute and dt.tm_sec == int_second):
checking_time = False # stop l
alarm_sound()
mixer.music.play()
else:
r.after(1000, check_time)
# --- main ---
running_alarm = False # default value at start
mixer.init()
r = tk.Tk()
r.title('Smart Watch')
message = tk.Label(r, text='What is the alarm message you\'d like to receive when the alarm goes off?',
font=('Roboto-regular', 12), fg='black')
message.pack()
entry_message = tk.Entry(r, width=45)
entry_message.pack()
enter_hour = tk.Label(r, text='Enter the hour for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_hour.pack()
entry_hour = tk.Entry(r, width=10)
entry_hour.pack()
enter_minute = tk.Label(r, text='Enter the minute for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_minute.pack()
entry_minute = tk.Entry(r, width=10)
entry_minute.pack()
enter_second = tk.Label(r, text='Enter the second for the alarm to go off: ',
font=('Roboto-regular', 12), fg='black')
enter_second.pack()
entry_second = tk.Entry(r, width=10)
entry_second.pack()
text_label = tk.Label(r, font=('Roboto-regular', 12, 'bold'), fg='tomato')
text_label.pack()
submit_button = tk.Button(r, text='Submit',
fg='black', width=30, height=2, relief='groove',
cursor='hand2', command=display_output)
submit_button.pack()
snooze_button = tk.Button(r, text='Snooze alarm',
fg='black',
width=30, height=2, relief='groove',
cursor='hand2', command=end)
snooze_button.pack()
r.mainloop()
Instead of the while True: loop, use a function and register a callback for the function every 'specified interval' of time. This is done in the code below:
def wait_for_alarm():
after = r.after(1000, wait_for_alarm) # 1000 refers to 1 second
if time.localtime().tm_hour == hr and time.localtime().tm_min == mn and time.localtime().tm_sec == sc:
print(message)
alarm_Sound()
mixer.music.play()

Why is my label not updating variable from different function? Tkinter

I am writing a time clock program. I have built the code, but have had trouble creating a GUI around it. I have entries that takes input and sends them to an outside function with a button event handling for calculation.
Running the program, I do not get a label updating the time. I wonder if it has to do with my textvariables.
from tkinter import *
import time
import os
def show_entry_fields():
hr= hrvar.get()
mn = minvar.get()
sc = secvar.get()
counter = int(hr)*3600+int(mn)*60+ int(sc)
mins = int(counter/60)
hours = int(mins/60)
hours = IntVar()
mins = IntVar()
secs = IntVar()
while counter > 0:
counter -= 1
hours, sec = divmod(counter, 3600)
mins, sec = divmod(sec, 60)
printv = StringVar()
printv = (" %d Hr:, %d Min: %d Sec" % (hours, mins, sec))
win1 = Tk()
timeLabel = Label(win1, textvariable= printv).grid(row=7)
mins= int(counter/60)
hours = int(mins/60)
time.sleep(1)
os.system('cls')
return
else:
finishedLabel = Label(master, text="Time is Up").grid(row=7)
return
master = Tk()
Label(master, text="Enter Hour(s)").grid(row=0)
Label(master, text="Enter Mins(s)").grid(row=1)
Label(master, text="Enter Second(s)").grid(row=2)
hrvar = IntVar()
minvar = IntVar()
secvar = IntVar()
e1 = Entry(master, textvariable = hrvar)
e2 = Entry(master, textvariable = minvar)
e3 = Entry(master, textvariable = secvar)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
Button(master, text='Quit', command=master.quit).grid(row=3, column=0,
sticky=W, pady=4)
Button(master, text='Show', command=show_entry_fields).grid(row=3,
column=1,
sticky=W, pady=4)
mainloop( )
Updated code.
class Timer:
def __init__(self, master):
#self.seconds = 0
self.time = StringVar()
self.hr = StringVar()
self.mins = StringVar()
self.secs = StringVar()
self.hr_label = Label(master, text='Enter Hours').pack()
self.entry_hr = Entry(master, textvariable = self.hr )
self.entry_hr.pack()
self.min_label = Label(master, text='Enter Minutes').pack()
self.entry_min = Entry(master, textvariable = self.mins)
self.entry_min.pack()
self.time_label = Label(master, relief='flat', font=("Cambria", 20),
textvariable=self.time)
self.set_time(hours= self.entry_hr.get(), minutes=self.entry_min.get(), seconds = 0)
self.time.set('00:00:00')
self.start_button = Button(master, text='Start')
self.start_button.bind('<Button-1>', self.start_countdown)
self.time_label.pack(padx=30, pady=10)
self.start_button.pack(pady=(10,20))
def set_time(self, hours, minutes, seconds):
self.seconds = hours * 3600 + minutes * 60 + seconds
self.time.set(self.format_time(self.seconds))
def start_countdown(self, event):
self.countdown()
def countdown(self):
if self.seconds <= 0:
return
self.seconds -= 1
self.time.set(self.format_time(self.seconds))
self.time_label.after(1000, self.countdown)
def format_time(self, seconds):
h = seconds // 3600
m = (seconds - h*3600) // 60
s = seconds - h*3600 - m*60
return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)
if __name__ == '__main__':
root = Tk()
timer = Timer(root)
#timer.set_time(hours=0, minutes=20, seconds=0)
root.mainloop()
There are several problems with your code. You are redefining printv, timeLabel, and creating a new Tk() object at every step in your while loop. More importantly, you define printv as a StringVar, but immediately redefine it as a string. You should define each of them once outside of the while loop and then use the set() method of printv.
Here is a very basic timer in Tkinter. First of all, you should not be using time.sleep or while loops. The mainloop function is already a while loop, and most tkinter objects have a .after() method that allows you to call events after a window of time (in milliseconds).
Notice that I created a class to encapsulate my entire UI. All variables are stored within the class and updated from its methods. The time is set within the script itself (currently to 1 hour, 20 minutes, 10 seconds), though that is easy to modify to accept args from the command line or from text fields in the UI.
from tkinter import Tk, Label, StringVar
from tkinter.ttk import Button, Entry
class Timer:
def __init__(self, master):
self.seconds = 0
self.time = StringVar()
self.time_label = Label(master, relief='flat', font=("Cambria", 20),
textvariable=self.time)
self.hr = StringVar()
self.hr_label = Label(master, text='Hours:').grid(row=1, column=1, padx=5, pady=1)
self.entry_hr = Entry(master, textvariable=self.hr, width=4)
self.entry_hr.grid(row=1, column=2)
self.mins = StringVar()
self.min_label = Label(master, text='Minutes:').grid(row=2, column=1, padx=5, pady=1)
self.entry_min = Entry(master, textvariable=self.mins, width=4)
self.entry_min.grid(row=2, column=2)
self.secs = StringVar()
self.secs_label = Label(master, text='Seconds:').grid(row=3, column=1, padx=5, pady=1)
self.entry_sec = Entry(master, textvariable=self.secs, width=4)
self.entry_sec.grid(row=3, column=2)
self.time.set('00:00:00')
self.start_button = Button(master, text='Start')
self.start_button.bind('<Button-1>', self.start_countdown)
self.time_label.grid(row=0, columnspan=4, padx=30, pady=10)
self.start_button.grid(row=4, columnspan=4, pady=(10,20))
def set_time(self, hours, minutes, seconds):
self.seconds = hours * 3600 + minutes * 60 + seconds
self.time.set(self.format_time(self.seconds))
def start_countdown(self, event):
h = self.entry_hr.get()
m = self.entry_min.get()
s = self.entry_sec.get()
h,m,s = map(lambda x: int(x) if x else 0, (h,m,s))
self.set_time(h,m,s)
self.countdown()
def countdown(self):
if self.seconds <= 0:
return
self.time.set(self.format_time(self.seconds))
self.seconds -= 1
self.time_label.after(1000, self.countdown)
def format_time(self, seconds):
h = seconds // 3600
m = (seconds - h*3600) // 60
s = seconds - h*3600 - m*60
return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)
if __name__ == '__main__':
root = Tk()
timer = Timer(root)
root.mainloop()

Categories

Resources