windows定时闹钟
import tkinter as tk
from tkinter import ttk, messagebox
import datetime, time, threading, json, os, pyttsx3
class AlarmClock:
def __init__(self):
self.root = tk.Tk()
self.root.title("定时闹钟")
self.root.geometry("500x400")
self.init_voice_engine()
self.config_file = "alarm_config.json"
self.custom_message = self.load_custom_message()
self.target_event = "上班" # 默认事件名称
self.setup_ui()
self.alarm_thread = None
self.voice_thread = None
self.is_running = False
self.is_alarming = False
def init_voice_engine(self):
self.engine = pyttsx3.init()
self.engine.setProperty('rate', 150)
self.engine.setProperty('volume', 1.0)
voices = self.engine.getProperty('voices')
for voice in voices:
if "chinese" in voice.id.lower():
self.engine.setProperty('voice', voice.id)
break
def num_to_chinese(self, num):
"""将数字转换为中文"""
chinese_numbers = {
'0': '零', '1': '一', '2': '二', '3': '三', '4': '四',
'5': '五', '6': '六', '7': '七', '8': '八', '9': '九', '10': '十'
}
if num <= 10:
return chinese_numbers.get(str(num), str(num))
elif num < 20:
return f"十{chinese_numbers.get(str(num-10), '')}"
elif num < 100:
tens = num // 10
ones = num % 10
if ones == 0:
return f"{chinese_numbers.get(str(tens), '')}十"
return f"{chinese_numbers.get(str(tens), '')}十{chinese_numbers.get(str(ones), '')}"
return str(num)
def generate_reminder_text(self, target_time):
"""生成动态提醒文本"""
now = datetime.datetime.now()
current_hour = now.hour
current_minute = now.minute
# 计算剩余时间(分钟)
time_diff = target_time - now
remaining_minutes = int(time_diff.total_seconds() / 60)
final_time = "2024-11-10 13:30:00"
final_time = datetime.datetime.strptime(final_time, "%Y-%m-%d %H:%M:%S")
time_diff = final_time - now
remaining_minutes = int(time_diff.total_seconds() / 60)
# 生成提醒文本
text = f"现在已经{self.num_to_chinese(current_hour)}点{self.num_to_chinese(current_minute)}分,"
text += f"距离{self.num_to_chinese(final_time.hour)}点{self.num_to_chinese(final_time.minute)}分{self.target_event}还剩{self.num_to_chinese(remaining_minutes)}分钟"
return text
def speak_loop(self, target_time):
"""循环播放动态语音"""
while self.is_alarming:
try:
# 生成动态提醒文本
reminder_text = self.generate_reminder_text(target_time)
# 更新状态显示
self.root.after(0, lambda: self.status_var.set(reminder_text))
# 播放语音
self.engine.say(reminder_text)
self.engine.runAndWait()
# 等待一段时间再播放下一次
time.sleep(2)
except Exception as e:
print(f"语音播放出错:{str(e)}")
time.sleep(1)
def start_alarm_sound(self, target_time):
"""开始循环播放警报声"""
self.is_alarming = True
self.voice_thread = threading.Thread(target=self.speak_loop,
args=(target_time,),
daemon=True)
self.voice_thread.start()
def stop_alarm_sound(self):
"""停止警报声"""
self.is_alarming = False
if self.voice_thread:
self.voice_thread.join(timeout=2)
def load_custom_message(self):
if os.path.exists(self.config_file):
try:
with open(self.config_file, 'r', encoding='utf-8') as f:
config = json.load(f)
return config.get('target_event', '上班')
except:
return '上班'
return '上班'
def save_custom_message(self):
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump({'target_event': self.target_event}, f, ensure_ascii=False)
def setup_ui(self):
# 时间设置框架
time_frame = ttk.LabelFrame(self.root, text="目标时间设置", padding="10")
time_frame.pack(fill="x", padx=10, pady=5)
# 小时选择
ttk.Label(time_frame, text="小时:").grid(row=0, column=0, padx=5)
self.hour_var = tk.StringVar(value="9")
self.hour_spinbox = ttk.Spinbox(time_frame, from_=0, to=23, width=5,
textvariable=self.hour_var)
self.hour_spinbox.grid(row=0, column=1, padx=5)
# 分钟选择
ttk.Label(time_frame, text="分钟:").grid(row=0, column=2, padx=5)
self.minute_var = tk.StringVar(value="0")
self.minute_spinbox = ttk.Spinbox(time_frame, from_=0, to=59, width=5,
textvariable=self.minute_var)
self.minute_spinbox.grid(row=0, column=3, padx=5)
# 事件名称设置
event_frame = ttk.LabelFrame(self.root, text="事件设置", padding="10")
event_frame.pack(fill="x", padx=10, pady=5)
ttk.Label(event_frame, text="事件名称:").pack(side="left", padx=5)
self.event_var = tk.StringVar(value=self.target_event)
self.event_entry = ttk.Entry(event_frame, textvariable=self.event_var)
self.event_entry.pack(side="left", fill="x", expand=True, padx=5)
# 测试按钮
self.test_button = ttk.Button(self.root, text="测试提示音",
command=self.test_voice)
self.test_button.pack(pady=5)
# 控制按钮
button_frame = ttk.Frame(self.root)
button_frame.pack(pady=10)
self.start_button = ttk.Button(button_frame, text="开始",
command=self.start_alarm)
self.start_button.pack(side="left", padx=5)
self.stop_button = ttk.Button(button_frame, text="停止",
command=self.stop_alarm,
state="disabled")
self.stop_button.pack(side="left", padx=5)
# 状态显示
self.status_var = tk.StringVar(value="未启动")
self.status_label = ttk.Label(self.root, textvariable=self.status_var,
wraplength=400) # 允许文本换行
self.status_label.pack(pady=10)
# 置顶按钮
self.topmost_var = tk.BooleanVar(value=False)
self.topmost_check = ttk.Checkbutton(self.root, text="窗口置顶",
variable=self.topmost_var,
command=self.toggle_topmost)
self.topmost_check.pack(pady=5)
def toggle_topmost(self):
self.root.attributes('-topmost', self.topmost_var.get())
def test_voice(self):
"""测试语音按钮的回调函数"""
try:
hours = int(self.hour_var.get())
minutes = int(self.minute_var.get())
target_time = datetime.datetime.now().replace(hour=hours, minute=minutes)
test_text = self.generate_reminder_text(target_time)
# 在新线程中播放测试语音
threading.Thread(target=lambda: self.engine.say(test_text) or
self.engine.runAndWait(),
daemon=True).start()
except ValueError:
messagebox.showerror("错误", "请输入有效的时间!")
def start_alarm(self):
try:
hours = int(self.hour_var.get())
minutes = int(self.minute_var.get())
if hours < 0 or hours > 23 or minutes < 0 or minutes > 59:
messagebox.showerror("错误", "请输入有效的时间!")
return
# 保存事件名称
self.target_event = self.event_var.get()
self.save_custom_message()
# 计算目标时间
target_time = datetime.datetime.now().replace(hour=hours,
minute=minutes,
second=0,
microsecond=0)
# 如果目标时间已过,设置为明天
if target_time <= datetime.datetime.now():
target_time += datetime.timedelta(days=1)
self.is_running = True
self.alarm_thread = threading.Thread(target=self.run_alarm,
args=(target_time,))
self.alarm_thread.daemon = True
self.alarm_thread.start()
self.start_button.config(state="disabled")
self.stop_button.config(state="normal")
self.status_var.set(f"闹钟将在 {target_time.strftime('%H:%M')} 响起")
except ValueError:
messagebox.showerror("错误", "请输入有效的数字!")
def stop_alarm(self):
self.is_running = False
self.stop_alarm_sound()
self.start_button.config(state="normal")
self.stop_button.config(state="disabled")
self.status_var.set("已停止")
def run_alarm(self, target_time):
while self.is_running:
now = datetime.datetime.now()
if now >= target_time:
# 开始循环播放动态警报声
self.start_alarm_sound(target_time)
break
time.sleep(1)
def run(self):
self.root.mainloop()
if __name__ == "__main__":
alarm = AlarmClock()
alarm.run()