windows定时闹钟

时间:2024-11-10 18:27:28
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()