0

I have just started using kivy and Tkinter to develop simple apps for starters. Recently, I created a digital Clock program that can be used on desktop. It works fine because it is simple with just a few lines of codes. I wanted to add one functionality which is Alarm. Can anyone please guide me on how to go about it.

It is my first time, so am not sure if I posted this question the right way or not. So below is the code I used to get my output.

import tkinter as tk
from tkinter.ttk import *

# I imported strftime to use for formatting time details of the program.
from time import strftime
import datetime

# creating tkinter window
root = tk.Tk()
root.title('Clock')
root.attributes('-topmost', True)  # This line here sets our app to be the 
topmost in the window screen.


# root.attributes('-topmost', False)   When this line is added, the app will 
no longer have that topmost privilege.


# This function will show us the calender on the program.
def datetime():
    string1 = strftime('%d/%b/%Y')  # This line can be joined with the other one  below with \n and it will work.
    lbl1.config(text=string1)
    lbl1.after(1000, datetime)


lbl1 = Label(root, font=('verdana', 20, 'bold'), background='black', 
foreground='#808000')
lbl1.pack(fill=tk.BOTH)
datetime()


# This function is used to display time on our label
def time():
    string = strftime('%H:%M:%S %p')
    lbl.config(text=string)
    lbl.after(1000, time) # updating the label.


# Giving the Label some style.
lbl = Label(root, font=('verdana', 22, 'bold'), background='#050929',
foreground='silver')

# packing the Label to the center.
# of the tkinter window
lbl.pack(anchor=tk.CENTER)
time()
root.mainloop()
Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
  • You can show a notification like Windows alarm & clock app using win10toast and pygame or some music library. But i recommend to not use notification as there is very little control over what we can do with them instead, show a window, like `messagebox` that does not close. – Delrius Euphoria Sep 20 '20 at 04:15
  • That is great, I will try adding that to the app. Like a button or something. If the user presses it, they get a messagebox that contain s a function which lets them set the alarm. Am not sure though if that is possible with the messagebox. – Hashim Rameel Sep 24 '20 at 01:10
  • Custom message? You have to use `simpledialog`. Check [here](https://docs.python.org/3.9/library/dialog.html#module-tkinter.simpledialog) – Delrius Euphoria Sep 24 '20 at 04:01

1 Answers1

1

For a procedural solution just add the after method of tkinter.

import tkinter as tk 
import datetime 

def tick():
    showed_time = '' 
    current_time = datetime.datetime.now().strftime("%H:%M:%S")
    if showed_time != current_time:
        showed_time = current_time
        clock.configure(text=current_time)
    clock.after(1000, tick)
    if showed_time == '10:00:00': #10 o'clock print alarm
        print('alarm')
    

root=tk.Tk()

clock = tk.Label(root)
clock.pack()
tick()


root.mainloop()

An object orientated solution could be this:

import tkinter as tk
from tkinter import ttk as ttk
import datetime     

root=tk.Tk()

class AlarmClock(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.all_alarms = []
        
        self.ini_body()
        self.ini_clock()
        self.ini_mid()
        self.ini_table()

    def ini_body(self):
        self.up_frame = tk.Frame(self)
        self.mid_frame= tk.Frame(self)
        self.dow_frame= tk.Frame(self)

        self.up_frame.pack(side='top')
        self.mid_frame.pack(side='top',fill='x')
        self.dow_frame.pack(side='top')

    def ini_clock(self):
        self.clock = tk.Label(self.up_frame, text='00:00:00')
        self.clock.pack(side='top', fill='x')
        self.tick()
    def tick(self):
        self.showed_time = ''
        self.current_time = datetime.datetime.now().strftime("%H:%M:%S")
        if self.showed_time != self.current_time:
            self.showed_time = self.current_time
            self.clock.configure(text=self.current_time)
        if self.showed_time in self.all_alarms:
            self.invoke_alarm(self.showed_time)
        self.after(1000, self.tick)

    def ini_table(self):
        self.table = ttk.Treeview(self.dow_frame,height=10,columns=('#1'))
        self.table.heading('#0', text='Alarm ID')
        self.table.heading('#1', text='Alarm time')

        self.table.pack()
    def ini_mid(self):
        self.alarm_id = tk.Entry(self.mid_frame,justify='center')
        self.alarm_id.insert('end','Alarm ID')

        self.alarm_time = tk.Entry(self.mid_frame,justify='center')
        self.alarm_time.insert('end','HH:MM')

        self.set_button = tk.Button(self.mid_frame, text='set alarm',
                                    command=self.set_alarm)
        self.cancel_button=tk.Button(self.mid_frame, text='cancel alarm',
                                     command=self.cancel_alarm)

        self.alarm_time.grid(column=1,row=0,sticky='ew')
        self.alarm_id.grid(column=0,row=0, sticky='we')
        self.set_button.grid(column=0, row=1, sticky='ew')
        self.cancel_button.grid(column=1, row=1, sticky='ew')
        self.mid_frame.columnconfigure(0, weight=1)
        self.mid_frame.columnconfigure(1, weight=1)
        
    def set_alarm(self):
        Id = self.alarm_id.get()
        time = self.alarm_time.get()
        self.table.insert('','end', iid=Id, text=Id,
                          values=time, tags=time)
        self.register_alarm()
    def cancel_alarm(self):
        Id = self.alarm_id.get()
        time = self.alarm_time.get()
        if self.table.exists(Id):
            tag = self.table.item(Id, "tags")[0]
            alarm_time=tag+":00"
            self.all_alarms.remove(alarm_time)
            self.table.delete(Id)
        elif self.table.tag_has(time):
            Id = self.table.tag_has(time)[0]
            tag = self.table.item(Id, "tags")[0]
            alarm_time=tag+":00"
            self.all_alarms.remove(alarm_time)
            self.table.delete(Id)
        
    def register_alarm(self):
        self.all_alarms.append(f'{self.alarm_time.get()}:00')
    def invoke_alarm(self, time):
        self.alarm_window = tk.Toplevel()
        self.alarm_window.title('Alarm!')

        self.message = tk.Label(self.alarm_window,
                                text=f"ALARM!! It's {time[:5]} o'clock!")
        self.message.pack(fill='both')

    

alarm = AlarmClock(root)
alarm.pack()


root.mainloop()

Hope you enjoy and let me know if you have any question about it.

Thingamabobs
  • 7,274
  • 5
  • 21
  • 54
  • I did enjoy every bit of your code. I am trying to learn new skills to develop apps so I copied your code and pasted it in my editor to understand it better. I realized that I needed to go back and rehearse the OOP part which I ignored before and seems very handy to create classes that inherit each other. Self-learning can be difficult but am giving it my best effort. – Hashim Rameel Sep 24 '20 at 01:17
  • @HashimRameel appreciate it, thanks. If you have some specific question on this code I would answer you. Another thing.. could you accept this answer to close this question by clicking the check icon next to my answer? – Thingamabobs Sep 24 '20 at 14:45
  • Thanks for your help. I am eager to develop apps with python especially desktop apps. Am not sure though if Tkinter is the best choice. Though it is easy to use but also outdated in terms of output and final appearance. Can you please recommend something? Please don't mind my little knowledge on the subject and also my English. I am learning all these things – Hashim Rameel Oct 03 '20 at 17:27
  • @HashimRameel I only use tkinter and you can create really good programs with it. But its true it needs some work to get there, cause I'm building all my widgets for myself with canvas. In the books I had read they recommand PyQt or PyGObject rather than tkinter. – Thingamabobs Oct 03 '20 at 17:51
  • I also to plan to continue with Tkinter before I move on to other modern GUI tools. I do have a simple clock that doesn't have any functions or classes just Tkinter and time modules imported. I want to add an alarm function to it using something like a menu and Entry for users to set their desired alarm time. Then the program plays a sound from files using the filedialog. All these should use minimum functions and classes as possible. – Hashim Rameel Oct 04 '20 at 20:05