import tkinter as tk from tkinter import ttk from datetime import datetime import pygame
#Initializing our audio mixer and setting the wav alarm file we want it to play when the alarm goes off pygame.mixer.init(42050, -16, 2, 2048) alarm_sound = pygame.mixer.Sound("MyAlarm.wav") #Setting our initial global values start_printed = False stop_printed = True done = False finished = False stop_clicked = False
class AlarmApp(tk.Tk): def init(self): tk.Tk.init(self) #Title of the window set to 'Alarm Clock'
self.title("Alarm Clock")
#Make it so user can't resize page
self.resizable(width = False, height = False)
#Set up all of the drop-down lists
self.hr = tk.IntVar(self)
self.min = tk.IntVar(self)
self.ampm = tk.StringVar(self)
#Set the initial values of each drop-down list
self.hr.set('12')
self.min.set("00")
self.ampm.set("AM")
#Create the list of values from which we are choosing from in our drop-down list
hours = []
minutes = []
ampmlist = ["AM","PM"]
#Hours go from 1 to 12
for x in range(1,13):
hours.append(x)
#Minutes go from 0 to 59
for y in range(0,60):
minutes.append("%02d" % (y,))
#Placing all of our list into the respective drop-down list
self.popmenuhours = tk.OptionMenu(self,self.hr, *hours)
self.popmenuminutes = tk.OptionMenu(self,self.min, *minutes)
self.popmenuAMPM = tk.OptionMenu(self, self.ampm, *ampmlist)
#Placing our drop-down lists on the page as well as one label
self.popmenuhours.pack(side = "left")
self.thing = tk.Label(text = ":").pack(side = "left")
self.popmenuminutes.pack(side = "left")
self.popmenuAMPM.pack(side = "left")
#Setting up all the buttons on the right hand side of the window. The text refers to what the button says
#Command refers to which function it will run once it's clicked
#State refers to whether it is clickable or not at the current state.
self.alarmbutton = tk.Button(self, text="Set Alarm", command=self.start_clock)
#I disabled both of these buttons since they should only be able to be pressed when it is appropriate and the alarm is running
self.cancelbutton = tk.Button(self, text="Cancel Alarm", command=self.stop_clock, state = "disabled")
self.stopalarmbutton = tk.Button(self, text = "Stop Alarm", command=self.stop_audio, state = "disabled")
#Packing all the buttons into the page
self.alarmbutton.pack()
self.cancelbutton.pack()
self.stopalarmbutton.pack()
def start_clock(self):
global done, start_printed, stop_printed, stop_clicked
#Done refers to whether either the time has been reached or if the user has cancelled. I.e: Loop is done.
if done == False:
#Cancel button is now active so user can decide at any point to cancel the alarm
self.cancelbutton.config(state = "active")
#Alarm button is now disabled since an alarm has currently already been set
self.alarmbutton.config(state = "disabled")
#On the first run of the loop, let the user know that an alarm has been set for their desired time
if start_printed == False:
#Print this notification for the user in the terminal
print("Alarm set for {}:{}{}".format(self.hr.get(), "%02d" % (self.min.get()),self.ampm.get()))
#Now set this to true, since we have printed it, so that it doesn't print it again on every loop for this set alarm
start_printed = True
#Stop printed set to false so that once the user cancels the timer, it will print a message (As we'll see later in the code)
stop_printed = False
#These next two if-statements are converting our hours from our drop-down list into 24-hour time, so that we can use it through DateTime
if self.ampm.get() == "AM":
if self.hr.get() in range(1,12):
hour_value = self.hr.get()
else:
hour_value = self.hr.get() - 12
if self.ampm.get() == "PM":
if self.hr.get() in range(1,12):
hour_value = self.hr.get() +12
else:
hour_value = self.hr.get()
#Now we call the Alarm function with the information that the user has entered to check whether we have reached the alarm time
self.Alarm("%02d" % (hour_value,), "%02d" % (self.min.get()))
#If user has clicked the cancel alarm button, we reset everything
if stop_clicked == True:
done = False
start_printed = False
stop_clicked = False
def stop_clock(self):
global done, stop_clicked
#Let the user know that the alarm has been cancelled by printing it in the terminal
print("Alarm set for {}:{}{} has been cancelled".format(self.hr.get(), "%02d" % (self.min.get()),self.ampm.get()))
#Cancel button has now been clicked
stop_clicked = True
#Now done with the current alarm/loop
done = True
#Buttons reset to what they were originally
self.cancelbutton.config(state = "disabled")
self.alarmbutton.config(state = "active")
def stop_audio(self):
#Use PyGame to stop the audio since button has been clicked
pygame.mixer.Sound.stop(alarm_sound)
#Stop alarm button disabled and alarm button active, essentially reseting everything
self.stopalarmbutton.config(state = "disabled")
self.alarmbutton.config(state = "active")
def Alarm(self,myhour,myminute):
global done, start_printed, finished
#If we are still not done, we follow this statement
if done == False:
#We convert the information into strings (To match DateTime)
myhour,myminute = str(myhour),str(myminute)
#Next, we extract the data of the current time from DateTime and take the information we want (hour and minute)
a = str(datetime.now())
b = a.split(" ")[1].split(":")
hour = b[0]
minute = b[1]
#Now, if the alarm time matches the current time, we follow his statement. Alarm is going to go off!
if hour == myhour and minute == myminute:
#Using pygame to play audio, loops = -1 refers to an infinite loop
pygame.mixer.Sound.play(alarm_sound, loops = -1)
print("Alarm is ringing!")
#We are now done
done = True
#Also finished
finished = True
#Now we change back the state of the cancel button to disabled, and the state of the alarm stop to active
#This is so the user can stop the alarm, since it will infinitely loop
self.cancelbutton.config(state = "disabled")
self.stopalarmbutton.config(state = "active")
else:
#If it is still not the set time, we recursively loop back to the start_clock function
self.after(1000, self.start_clock)
done = False
#If we are finished, which we are when the alarm goes off, we reset everything
if finished == True:
start_printed = False
finished = False
app = AlarmApp() app.mainloop()