Reputation: 25
so I have a basic alarm python GUI, nothing fancy is still in need of a lot of work. So currently my code works as follow: The user clicks "create new alarm" and it opens a window with 3 option menu widgets and selected the time he wants the alarm to go off, then once the set alarm is clicked a loop is run that counts down at one second every time the loop is repeated and the time is printed in the console than when the time they set is equal to the current time the alarm goes off.
Now my problem is that I want that countdown that is in the console to be displayed on the GUI. I tried to simply make a label and use .get to fetch the current value and display them but once the loop starts it won't do any other code. If I have any other suggestions I am all ears. All i want is a countdown that shows how much time till the alarm goes off, my current idea in my trial and error plan is to display the console.
Here is my code:
# Import Required Library
from tkinter import *
import datetime
import time
import winsound
from threading import *
from tkinter import messagebox
def submit():
def alarm(Curent):
# Infinite Loop
while True:
# Set Alarm
set_alarm_time = f"{hour.get()}:{minute.get()}:{second.get()}"
# Wait for one seconds
time.sleep(1)
# Get current time
current_time = datetime.datetime.now().strftime("%H:%M:%S")
print(current_time,set_alarm_time)
Curent = current_time
set = set_alarm_time
# Check whether set alarm is equal to current time or not
if current_time == set_alarm_time:
print("Time to Wake up")
# Playing sound
winsound.PlaySound("sound.wav",winsound.SND_ASYNC)
messagebox.showinfo(title="ALARM", message="Alarm is going off, its time to wake up!")
break
root = Tk()
root.geometry("400x300")
root.config(bg="#447c84")
root.title('MathAlarm')
# Add Labels, Frame, Button, Optionmenus
Label(root,text="Alarm Clock",font=("Helvetica 20 bold"),fg="Black").pack(pady=10)
Label(root,text="Set Time",font=("Helvetica 15 bold")).pack()
frame = Frame(root)
frame.pack()
hour = StringVar(root)
hours = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23', '24'
)
hour.set(hours[0])
hrs = OptionMenu(frame, hour, *hours)
hrs.pack(side=LEFT)
minute = StringVar(root)
minutes = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23',
'24', '25', '26', '27', '28', '29', '30', '31',
'32', '33', '34', '35', '36', '37', '38', '39',
'40', '41', '42', '43', '44', '45', '46', '47',
'48', '49', '50', '51', '52', '53', '54', '55',
'56', '57', '58', '59', '60')
minute.set(minutes[0])
mins = OptionMenu(frame, minute, *minutes)
mins.pack(side=LEFT)
second = StringVar(root)
seconds = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23',
'24', '25', '26', '27', '28', '29', '30', '31',
'32', '33', '34', '35', '36', '37', '38', '39',
'40', '41', '42', '43', '44', '45', '46', '47',
'48', '49', '50', '51', '52', '53', '54', '55',
'56', '57', '58', '59', '60')
second.set(seconds[0])
secs = OptionMenu(frame, second, *seconds)
secs.pack(side=LEFT)
Button(root,text="Set Alarm",font=("Helvetica 15"),command=alarm).pack(pady=20)
Button(root,text="Exit",font=("Helvetica 15"), command=lambda:root.destroy()).pack(pady=20)
root = Tk()
root.title('MathAlarm')
root.geometry('347x400')
root.config(bg="#447c84")
welcomelabel = Label(root, text="Welcome to Math Alarm", font=("Times", "24", "bold"))
welcomelabel.pack()
ext = Button(root, text="Exit", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=lambda:root.destroy())
reg = Button(root, text="Create new Alarm", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)
ext.pack()
reg.pack()
# Execute Tkinter
root.mainloop()`
Upvotes: 1
Views: 419
Reputation: 2690
Well I tried a different approach which does not uses the custom threading at all but uses tkinter's own main loop, it has it's own drawbacks and advantages too. I made following changes in your code to make it work
There is an option in the tkinter to run a function withing the main loop of tkinter periodically that way you won't be blocking any events processing of tkinter or any other process as tkinter itself take care of that check documentation of root.after(time, function) for more details.
# Import Required Library
from tkinter import *
import datetime
import time
import winsound
from threading import *
from tkinter import messagebox
mainLabel = None
(h, m, s) = (None, None, None)
root = None
def alarm():
global mainLabel
set_alarm_time = f"{h}:{m}:{s}"
current_time = datetime.datetime.now().strftime('%H:%M:%S')
mainLabel['text'] = current_time #update current time in label, you can show whatever you want
print(current_time, set_alarm_time)
# Check whether set alarm is equal to current time or not
if current_time == set_alarm_time:
print("Time to Wake up")
# Playing sound
winsound.PlaySound("sound.wav", winsound.SND_ASYNC)
messagebox.showinfo(title="ALARM", message="Alarm is going off, its time to wake up!")
#no more need to schedule the function
else:
#alarm time is not reached let's schedule the function again for one second
root.after(1000, alarm)
def submit():
global mainLabel
def start():
global h, m, s, hours, mins, secs
print('scheduling alarm')
h = hour.get()
m = minute.get()
s = second.get()
(hours, mins, secs) = (int(h), int(m), int(s))
root.after(1000, alarm)
root = Tk()
root.geometry("400x300")
root.config(bg="#447c84")
root.title('MathAlarm')
# Add Labels, Frame, Button, Optionmenus
Label(root,text="Alarm Clock",font=("Helvetica 20 bold"),fg="Black").pack(pady=10)
mainLabel = Label(root,text="Set Time",font=("Helvetica 15 bold"))
mainLabel.pack()
frame = Frame(root)
frame.pack()
hour = StringVar(root)
hours = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23', '24'
)
hour.set(hours[0])
hrs = OptionMenu(frame, hour, *hours)
hrs.pack(side=LEFT)
minute = StringVar(root)
minutes = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23',
'24', '25', '26', '27', '28', '29', '30', '31',
'32', '33', '34', '35', '36', '37', '38', '39',
'40', '41', '42', '43', '44', '45', '46', '47',
'48', '49', '50', '51', '52', '53', '54', '55',
'56', '57', '58', '59', '60')
minute.set(minutes[0])
mins = OptionMenu(frame, minute, *minutes)
mins.pack(side=LEFT)
second = StringVar(root)
seconds = ('00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '10', '11', '12', '13', '14', '15',
'16', '17', '18', '19', '20', '21', '22', '23',
'24', '25', '26', '27', '28', '29', '30', '31',
'32', '33', '34', '35', '36', '37', '38', '39',
'40', '41', '42', '43', '44', '45', '46', '47',
'48', '49', '50', '51', '52', '53', '54', '55',
'56', '57', '58', '59', '60')
second.set(seconds[0])
secs = OptionMenu(frame, second, *seconds)
secs.pack(side=LEFT)
Button(root,text="Set Alarm",font=("Helvetica 15"), command=start).pack(pady=20)
Button(root,text="Exit",font=("Helvetica 15"), command=lambda:root.destroy()).pack(pady=20)
root = Tk()
root.title('MathAlarm')
root.geometry('347x400')
root.config(bg="#447c84")
welcomelabel = Label(root, text="Welcome to Math Alarm", font=("Times", "24", "bold"))
welcomelabel.pack()
ext = Button(root, text="Exit", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=lambda:root.destroy())
reg = Button(root, text="Create new Alarm", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)
ext.pack()
reg.pack()
root.mainloop()
The output is following
NOTE: The answer is only for showing, how to update tkinter's label value in GUI which was the actual problem.
Upvotes: 1