DEV Community

Mate Technologies
Mate Technologies

Posted on

πŸ•°οΈ Building a Modern Alarm Clock App in Python with Tkinter

Modern Alarm Clock App Dashboard

Tkinter often gets a bad reputation for looking outdated β€” but with the right tools and structure, you can build modern, feature-rich desktop apps using pure Python.

In this article, we’ll build MateTools – Alarm Clock, a full-featured alarm clock with:

Multiple alarms

Recurring schedules

Snooze functionality

Time zone support

Live countdown timers

Dark / Light mode

A clean tabbed UI

All using Tkinter, ttk, and sv_ttk.

Modern Alarm Clock App - Set Alarm

πŸš€ Features Overview

⏰ Multiple alarms with custom labels

πŸ” Recurring alarms: Once, Daily, Weekdays, Weekends

😴 Snooze support

🌍 Time zone aware alarms (via pytz)

⏳ Live countdown timers per alarm

🎨 Dark / Light mode toggle

πŸ“‹ Active alarms dashboard

🧡 Threaded alarm engine (non-blocking UI)

🧰 Requirements

Install the required packages:

pip install sv-ttk pytz

winsound is Windows-only. This app is designed for Windows.

🧠 Architecture Highlights

Threading is used so alarms don’t freeze the UI

Dictionary-based alarm objects store state cleanly

pytz ensures accurate cross-timezone alarms

sv_ttk modernizes Tkinter’s look instantly

🧩 Full Source Code

βœ… This is the complete working application

import tkinter as tk
from tkinter import ttk, messagebox
import sv_ttk
import datetime
import threading
import winsound
import pytz

# =========================
# App Setup
# =========================
root = tk.Tk()
root.title("MateTools - Alarm Clock")
root.geometry("950x620")
sv_ttk.set_theme("light")

# =========================
# Globals
# =========================
alarms = []
dark_mode_var = tk.BooleanVar(value=False)
timezone_var = tk.StringVar(value="UTC")

# =========================
# Helpers
# =========================
def set_status(msg):
    status_var.set(msg)
    root.update_idletasks()

def toggle_theme():
    if dark_mode_var.get():
        sv_ttk.set_theme("dark")
        set_status("Theme switched to Dark mode")
    else:
        sv_ttk.set_theme("light")
        set_status("Theme switched to Light mode")

# =========================
# Status Bar
# =========================
status_var = tk.StringVar(value="Ready")
ttk.Label(root, textvariable=status_var, anchor="w",
          font=("Segoe UI", 10)).pack(side=tk.BOTTOM, fill="x")

# =========================
# Alarm Logic
# =========================
def alarm_thread(alarm):
    tz = pytz.timezone(timezone_var.get())
    while alarm["running"]:
        now = datetime.datetime.now(tz)
        weekday = now.weekday()

        alarm_time = datetime.datetime.strptime(
            alarm["time"], "%H:%M:%S"
        ).replace(year=now.year, month=now.month, day=now.day)

        alarm_time = tz.localize(alarm_time)
        if alarm_time < now:
            alarm_time += datetime.timedelta(days=1)

        remaining = alarm_time - now
        h, r = divmod(int(remaining.total_seconds()), 3600)
        m, s = divmod(r, 60)
        alarm["remaining_var"].set(f"{h:02d}:{m:02d}:{s:02d}")

        if now.strftime("%H:%M:%S") == alarm["time"]:
            if (
                alarm["recurring"] == "Once"
                or alarm["recurring"] == "Daily"
                or alarm["recurring"] == "Weekdays" and weekday < 5
                or alarm["recurring"] == "Weekends" and weekday >= 5
            ):
                winsound.Beep(1000, 1000)
                snooze = messagebox.askyesno(
                    "Alarm", f"{alarm['label']} - Time's up!\nSnooze?"
                )

                if snooze:
                    future = now + datetime.timedelta(minutes=alarm["snooze"])
                    alarm["time"] = future.strftime("%H:%M:%S")
                else:
                    if alarm["recurring"] == "Once":
                        alarm["running"] = False
                        refresh_alarm_list()

        threading.Event().wait(0.5)

# =========================
# Alarm Management
# =========================
def refresh_alarm_list():
    for w in alarm_list_frame.winfo_children():
        w.destroy()

    for i, alarm in enumerate(alarms):
        row = ttk.Frame(alarm_list_frame)
        row.pack(fill="x", pady=3)

        ttk.Label(row, text=f"{alarm['label']} ({alarm['recurring']})",
                  font=("Segoe UI", 12)).pack(side="left", padx=5)

        ttk.Label(row, textvariable=alarm["remaining_var"],
                  font=("Consolas", 12, "bold")).pack(side="left", padx=10)

        ttk.Button(row, text="Stop",
                   command=lambda i=i: stop_alarm(i)).pack(side="right", padx=5)

        ttk.Button(row, text="Delete",
                   command=lambda i=i: delete_alarm(i)).pack(side="right", padx=5)

def add_alarm():
    try:
        datetime.datetime.strptime(alarm_time_var.get(), "%H:%M:%S")
    except ValueError:
        messagebox.showerror("Error", "Time format must be HH:MM:SS")
        return

    alarm = {
        "time": alarm_time_var.get(),
        "label": alarm_label_var.get(),
        "recurring": alarm_recurring_var.get(),
        "snooze": alarm_snooze_var.get(),
        "running": True,
        "remaining_var": tk.StringVar(value="00:00:00")
    }

    t = threading.Thread(target=alarm_thread, args=(alarm,), daemon=True)
    alarm["thread"] = t
    alarms.append(alarm)
    t.start()

    refresh_alarm_list()
    set_status(f"Alarm '{alarm['label']}' added")

def stop_alarm(i):
    alarms[i]["running"] = False
    refresh_alarm_list()

def delete_alarm(i):
    alarms[i]["running"] = False
    alarms.pop(i)
    refresh_alarm_list()

# =========================
# UI Tabs
# =========================
tabs = ttk.Notebook(root)
tabs.pack(expand=True, fill="both", padx=20, pady=20)

# Dashboard
dash = ttk.Frame(tabs, padding=20)
tabs.add(dash, text="🏠 Dashboard")

ttk.Label(dash, text="MateTools - Alarm Clock",
          font=("Segoe UI", 20, "bold")).pack(anchor="w")

ttk.Label(dash,
          text="A modern productivity alarm clock built with Python.",
          font=("Segoe UI", 14)).pack(anchor="w", pady=10)

# Set Alarm
set_tab = ttk.Frame(tabs, padding=20)
tabs.add(set_tab, text="⏰ Set Alarm")

alarm_time_var = tk.StringVar(value="07:00:00")
alarm_label_var = tk.StringVar(value="Alarm")
alarm_recurring_var = tk.StringVar(value="Once")
alarm_snooze_var = tk.IntVar(value=5)

frame = ttk.LabelFrame(set_tab, text="Alarm Settings", padding=20)
frame.pack(fill="x")

fields = [
    ("Time (HH:MM:SS)", alarm_time_var),
    ("Label", alarm_label_var),
]

for i, (label, var) in enumerate(fields):
    ttk.Label(frame, text=label).grid(row=i, column=0, sticky="e", padx=10, pady=6)
    ttk.Entry(frame, textvariable=var, width=30).grid(row=i, column=1, padx=10)

ttk.Label(frame, text="Recurring").grid(row=2, column=0, sticky="e")
ttk.Combobox(frame, textvariable=alarm_recurring_var,
             values=["Once", "Daily", "Weekdays", "Weekends"],
             state="readonly").grid(row=2, column=1)

ttk.Label(frame, text="Snooze (minutes)").grid(row=3, column=0, sticky="e")
ttk.Entry(frame, textvariable=alarm_snooze_var).grid(row=3, column=1)

ttk.Label(frame, text="Time Zone").grid(row=4, column=0, sticky="e")
ttk.Combobox(frame, textvariable=timezone_var,
             values=pytz.all_timezones,
             state="readonly").grid(row=4, column=1)

ttk.Button(frame, text="Add Alarm",
           command=add_alarm).grid(row=5, column=0, columnspan=2, pady=15)

ttk.Checkbutton(set_tab, text="Dark Mode",
                variable=dark_mode_var,
                command=toggle_theme).pack(pady=10)

# Active Alarms
active_tab = ttk.Frame(tabs, padding=20)
tabs.add(active_tab, text="πŸ“‹ Active Alarms")

alarm_list_frame = ttk.Frame(active_tab)
alarm_list_frame.pack(fill="both", expand=True)

root.mainloop()
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Possible Improvements

Cross-platform sound support (playsound)

Persistent alarms (save to file)

System tray minimization

Notification API integration

macOS / Linux compatibility

πŸ”— About MateTools

MateTools builds practical, clean, and secure desktop tools designed for everyday productivity.

πŸ‘‰ https://matetools.gumroad.com

Modern Alarm Clock App - Active Alarms

Top comments (0)