iT邦幫忙

0

[Day 28]多鬧鐘提醒器 GUI 基礎版

  • 分享至 

  • xImage
  •  

今天做一個本機鬧鐘:加入多個 HH:MM 時間,到點就跳出提醒並嗶一聲。
全程使用 Python 標準庫(Tkinter、datetime),零安裝、跨 Windows/macOS/Linux 可跑。

今天要解決的痛點

  • 只想快速設幾個固定時間提醒(喝水、開會、下課鐘),不想裝厚重 App。
  • 想一次放多個鬧鐘、每天重複,到點能看到彈窗且聽到提示音。
  • 介面要簡單:新增/刪除/靜音三件事就夠了。

功能清單

  • 多鬧鐘:24 小時制 HH:MM,支援多組時間。
  • 每日重複:跨日自動重置,同一分鐘只提醒一次。
  • 桌面提醒+嗶聲:messagebox 彈窗+ root.bell()。
  • 靜音開關:開會時只跳窗不出聲。
  • 不卡 UI:用 after 每秒輕量檢查,不會凍結視窗。
  • 快捷鍵:Enter 新增、Delete 刪除選取。

程式碼(存成 alarm_basic.py)

import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime
import re

ALARMS = set()               # "HH:MM"
MUTED = False
FIRED_TODAY = set()          # 記錄今日已觸發(避免同分鐘重複)
HHMM_RE = re.compile(r"^(?:[01]\d|2[0-3]):[0-5]\d$")

def now_hhmm(): return datetime.now().strftime("%H:%M")

def add_alarm():
    s = entry.get().strip()
    if not HHMM_RE.match(s):
        messagebox.showerror("格式錯誤","請輸入 24 小時制時間,如 08:30、19:05"); return
    if s in ALARMS:
        messagebox.showinfo("提示", f"{s} 已存在"); return
    ALARMS.add(s); refresh_list(); entry.delete(0, tk.END)

def delete_selected():
    sel = listbox.curselection()
    if not sel: return
    hhmm = listbox.get(sel[0]).split()[0]
    ALARMS.discard(hhmm); refresh_list()

def refresh_list():
    listbox.delete(0, tk.END)
    for t in sorted(ALARMS): listbox.insert(tk.END, f"{t}  (每日)")

def toggle_mute():
    global MUTED
    MUTED = not MUTED
    mute_btn.config(text=("解除靜音" if MUTED else "靜音"))

def tick_clock():
    clock_var.set(f"現在時間:{now_hhmm()}"); root.after(1000, tick_clock)

def check_loop():
    # 每秒檢查鬧鐘;跨日 00:00 會自動清空 FIRED_TODAY
    now = datetime.now()
    hhmm = now.strftime("%H:%M")
    if hhmm == "00:00" and now.second == 0:
        FIRED_TODAY.clear()
    if hhmm in ALARMS and hhmm not in FIRED_TODAY:
        FIRED_TODAY.add(hhmm); notify(hhmm)
    root.after(1000, check_loop)

def notify(hhmm):
    if not MUTED:
        try: root.bell()
        except Exception: pass
    messagebox.showinfo("時間到!", f"{hhmm} 到點囉!")

# ----- GUI -----
root = tk.Tk(); root.title("多鬧鐘(基礎版)")
main = ttk.Frame(root, padding=16); main.grid(sticky="nsew")
root.columnconfigure(0, weight=1); root.rowconfigure(0, weight=1)
main.columnconfigure(0, weight=1); main.rowconfigure(2, weight=1)

row = ttk.Frame(main); row.grid(row=0, column=0, sticky="we")
ttk.Label(row, text="新增鬧鐘(HH:MM)").grid(row=0, column=0, padx=(0,8))
entry = ttk.Entry(row, width=8, justify="center"); entry.grid(row=0, column=1)
ttk.Button(row, text="加入", command=add_alarm).grid(row=0, column=2, padx=6)
mute_btn = ttk.Button(row, text="靜音", command=toggle_mute); mute_btn.grid(row=0, column=3)

clock_var = tk.StringVar(value=f"現在時間:{now_hhmm()}")
ttk.Label(main, textvariable=clock_var).grid(row=1, column=0, sticky="w", pady=(8,4))

listbox = tk.Listbox(main, height=10); listbox.grid(row=2, column=0, sticky="nsew")
scroll = ttk.Scrollbar(main, orient="vertical", command=listbox.yview)
scroll.grid(row=2, column=1, sticky="ns"); listbox.configure(yscrollcommand=scroll.set)

ops = ttk.Frame(main); ops.grid(row=3, column=0, sticky="we", pady=(8,0))
ttk.Button(ops, text="刪除選取", command=delete_selected).grid(row=0, column=0, padx=4)
ttk.Button(ops, text="離開", command=root.destroy).grid(row=0, column=1, padx=4)

root.bind("<Return>", lambda e: add_alarm())
root.bind("<Delete>", lambda e: delete_selected())

tick_clock(); check_loop(); entry.focus()
root.mainloop()

使用方式

python alarm_basic.py

  1. 在輸入框打 08:30 → 按「加入」。
  2. 再加入 12:00、19:05 等多組時間。
  3. 到點會彈窗+嗶聲提醒;若不想出聲,按「靜音」。
  4. 要刪除某個鬧鐘,選取後按「Delete」或點「刪除選取」。

實作:
https://ithelp.ithome.com.tw/upload/images/20251022/20169368ouhB2PiXYO.png

常見問題(FAQ)

  • 輸入格式錯誤? 只接受 00:00~23:59 的 24 小時制,例如 08:05。
  • 會不會一直跳? 同一分鐘只提醒一次(設有 FIRED_TODAY 記錄)。到隔天 00:00 自動清空。
  • 可以保存鬧鐘嗎? 本版只在記憶體。若要開啟程式就載入既有鬧鐘,可把集合 ALARMS 讀寫到 alarms.txt(第 29 天會做「匯入/匯出」進階版)。
  • 為什麼用 after 而不是 while True? after 屬於 Tk 的事件循環,不會阻塞 UI,視窗保持流暢。

今日小結

  1. 用不到百行的 Tkinter 程式,做出每日多鬧鐘。
  2. 核心在於:正規檢查時間 → 集合儲存鬧鐘 → after 每秒檢查 → 到點提醒。
  3. 明天(Day 29):進階版加上每週重複、備註、匯入/匯出 CSV,到點顯示備註,更貼近日常使用。

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言