用Python写一个事件提醒的脚本

文章目录

一、界面展示

二、脚本功能

1. 核心功能

2. 界面功能

3. 安全性功能

三、使用方法

四、代码实现

1. 类结构设计

2. 关键方法实现

a. 创建界面组件

b. 设置单次提醒

c. 设置重复提醒

d. 删除提醒

3. 关键技术点

a. 多线程处理

b. 定时器实现

c. 数据存储

4. 错误处理

五、完整代码

六、总结

七、注意事项

一、界面展示

二、脚本功能

1. 核心功能

单次提醒功能:在指定日期和时间弹出提醒
重复提醒功能:支持每天/每周/每月定时提醒
删除提醒功能:可以删除已设置的提醒
提醒列表显示:实时显示所有设置的提醒

2. 界面功能

使用选项卡分类显示不同类型的提醒设置
提供图形化界面输入
实时显示提醒列表
错误提示和成功确认提示

3. 安全性功能

输入验证:检查必填字段
时间验证:防止设置过去的时间
格式验证:确保日期和时间格式正确

三、使用方法

1. 单次提醒

2. 重复提醒设置

3. 删除提醒

四、代码实现

1. 类结构设计

class ReminderApp:
    def __init__(self):
        # 初始化主窗口
        self.root = tk.Tk()
        # 初始化提醒字典
        self.reminders = {}
        # 创建界面组件
        self.create_widgets()
        # 启动调度线程
        self.schedule_thread = threading.Thread(target=self.run_schedule, daemon=True)

2. 关键方法实现

a. 创建界面组件

def create_widgets(self):
    # 创建选项卡
    self.notebook = ttk.Notebook(self.root)
    # 创建单次提醒和重复提醒标签页
    self.single_frame = ttk.Frame(self.notebook)
    self.repeat_frame = ttk.Frame(self.notebook)
    # 创建提醒列表
    self.reminder_list = tk.Listbox(self.root)

b. 设置单次提醒

def set_single_reminder(self):
    # 获取用户输入
    date_str = self.date_entry.get()
    time_str = self.single_time_entry.get()
    message = self.single_message_entry.get()
    
    # 验证输入
    if not all([date_str, time_str, message]):
        messagebox.showerror("错误", "请填写所有字段")
        return
        
    try:
        # 创建定时器
        reminder_datetime = datetime.strptime(f"{date_str} {time_str}", 
                                           "%Y-%m-%d %H:%M")
        delay = (reminder_datetime - datetime.now()).total_seconds()
        timer = threading.Timer(delay, self.show_reminder, 
                              args=[message, reminder_id])
        
        # 保存提醒信息
        self.reminders[reminder_id] = {
            'datetime': reminder_datetime,
            'message': message,
            'timer': timer,
            'repeat': False
        }

c. 设置重复提醒

def set_repeat_reminder(self):
    # 获取用户输入
    time_str = self.repeat_time_entry.get()
    message = self.repeat_message_entry.get()
    repeat_type = self.repeat_type.get()
    
    try:
        # 根据重复类型设置调度任务
        if repeat_type == "daily":
            job = schedule.every().day.at(time_str).do(
                self.show_reminder, message, reminder_id)
        # 保存提醒信息
        self.reminders[reminder_id] = {
            'time': time_str,
            'message': message,
            'job': job,
            'repeat': True,
            'repeat_type': repeat_type
        }

d. 删除提醒

def delete_reminder(self):
    # 获取选中的提醒
    selection = self.reminder_list.curselection()
    if not selection:
        messagebox.showwarning("警告", "请先选择要删除的提醒")
        return
    
    # 删除提醒
    reminder_id = list(self.reminders.keys())[selection[0]]
    self.remove_reminder(reminder_id)
    self.update_reminder_list()

3. 关键技术点

a. 多线程处理

# 使用守护线程运行调度器
self.schedule_thread = threading.Thread(target=self.run_schedule, daemon=True)
self.schedule_thread.start()

b. 定时器实现

# 单次提醒使用 threading.Timer
timer = threading.Timer(delay, self.show_reminder, args=[message, reminder_id])

# 重复提醒使用 schedule 库
schedule.every().day.at(time_str).do(self.show_reminder, message, reminder_id)

c. 数据存储

# 使用字典存储所有提醒
self.reminders = {
    'reminder_id': {
        'datetime': datetime_obj,  # 对于单次提醒
        'time': time_str,         # 对于重复提醒
        'message': message,
        'timer/job': timer_or_job_obj,
        'repeat': boolean,
        'repeat_type': type_str   # 对于重复提醒
    }
}

4. 错误处理

try:
    # 时间格式转换
    reminder_datetime = datetime.strptime(f"{date_str} {time_str}", 
                                        "%Y-%m-%d %H:%M")
    # 验证时间是否有效
    if reminder_datetime < datetime.now():
        messagebox.showerror("错误", "不能设置过去的时间")
        return
except ValueError:
    messagebox.showerror("错误", "日期或时间格式错误")

五、完整代码

import tkinter as tk
from tkinter import messagebox, ttk
import time
import schedule
import threading
from datetime import datetime, timedelta
import platform
import os

# 根据操作系统选择声音模块
if platform.system() == 'Windows':
    import winsound


    def play_alert():
        winsound.Beep(1000, 1000)  # 频率1000Hz,持续1000毫秒
else:
    def play_alert():
        os.system('play -nq -t alsa synth 1 sine 440')  # Linux系统下的提示音


class ReminderApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("定时提醒")
        self.root.geometry("400x600")

        # 存储所有提醒的字典
        self.reminders = {}

        # 声音开关变量
        self.sound_enabled = tk.BooleanVar(value=True)

        # 创建输入框和按钮
        self.create_widgets()

        # 创建一个线程来运行调度器
        self.schedule_thread = threading.Thread(target=self.run_schedule, daemon=True)
        self.schedule_thread.start()

    def create_widgets(self):
        # 创建notebook用于切换不同类型的提醒设置
        self.notebook = ttk.Notebook(self.root)
        self.notebook.pack(pady=5, expand=True, fill="both")

        # 单次提醒标签页
        self.single_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.single_frame, text="单次提醒")

        # 重复提醒标签页
        self.repeat_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.repeat_frame, text="重复提醒")

        # 设置单次提醒的控件
        self.setup_single_reminder_widgets()

        # 设置重复提醒的控件
        self.setup_repeat_reminder_widgets()

        # 声音控制区域
        sound_frame = ttk.LabelFrame(self.root, text="声音设置")
        sound_frame.pack(pady=5, padx=5, fill="x")

        # 声音开关复选框
        self.sound_checkbox = tk.Checkbutton(sound_frame, text="启用提醒声音",
                                             variable=self.sound_enabled)
        self.sound_checkbox.pack(side=tk.LEFT, padx=5)

        # 测试声音按钮
        self.test_sound_button = tk.Button(sound_frame, text="测试提醒声音",
                                           command=self.test_sound)
        self.test_sound_button.pack(side=tk.RIGHT, padx=5)

        # 提醒列表框架
        list_frame = ttk.LabelFrame(self.root, text="提醒列表")
        list_frame.pack(pady=5, padx=5, fill="both", expand=True)

        # 提醒列表
        self.reminder_list = tk.Listbox(list_frame, width=50, height=10)
        self.reminder_list.pack(pady=5, padx=5, fill="both", expand=True)

        # 删除提醒按钮
        self.delete_button = tk.Button(list_frame, text="删除选中的提醒",
                                       command=self.delete_reminder)
        self.delete_button.pack(pady=5)

    def setup_single_reminder_widgets(self):
        # 日期输入
        date_frame = ttk.Frame(self.single_frame)
        date_frame.pack(pady=5, fill="x")
        ttk.Label(date_frame, text="日期 (YYYY-MM-DD):").pack(side=tk.LEFT, padx=5)
        self.date_entry = ttk.Entry(date_frame)
        self.date_entry.pack(side=tk.LEFT, expand=True, fill="x", padx=5)
        self.date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))

        # 时间输入
        time_frame = ttk.Frame(self.single_frame)
        time_frame.pack(pady=5, fill="x")
        ttk.Label(time_frame, text="时间 (HH:MM):").pack(side=tk.LEFT, padx=5)
        self.single_time_entry = ttk.Entry(time_frame)
        self.single_time_entry.pack(side=tk.LEFT, expand=True, fill="x", padx=5)

        # 提醒内容输入
        message_frame = ttk.Frame(self.single_frame)
        message_frame.pack(pady=5, fill="x")
        ttk.Label(message_frame, text="提醒内容:").pack(side=tk.LEFT, padx=5)
        self.single_message_entry = ttk.Entry(message_frame)
        self.single_message_entry.pack(side=tk.LEFT, expand=True, fill="x", padx=5)

        # 设置提醒按钮
        self.single_set_button = ttk.Button(self.single_frame, text="设置单次提醒",
                                            command=self.set_single_reminder)
        self.single_set_button.pack(pady=10)

    def setup_repeat_reminder_widgets(self):
        # 时间输入
        time_frame = ttk.Frame(self.repeat_frame)
        time_frame.pack(pady=5, fill="x")
        ttk.Label(time_frame, text="时间 (HH:MM):").pack(side=tk.LEFT, padx=5)
        self.repeat_time_entry = ttk.Entry(time_frame)
        self.repeat_time_entry.pack(side=tk.LEFT, expand=True, fill="x", padx=5)

        # 提醒内容输入
        message_frame = ttk.Frame(self.repeat_frame)
        message_frame.pack(pady=5, fill="x")
        ttk.Label(message_frame, text="提醒内容:").pack(side=tk.LEFT, padx=5)
        self.repeat_message_entry = ttk.Entry(message_frame)
        self.repeat_message_entry.pack(side=tk.LEFT, expand=True, fill="x", padx=5)

        # 重复类型选择
        repeat_type_frame = ttk.LabelFrame(self.repeat_frame, text="重复类型")
        repeat_type_frame.pack(pady=5, padx=5, fill="x")

        self.repeat_type = tk.StringVar(value="daily")
        repeat_options = [
            ("每天", "daily"),
            ("每周", "weekly"),
            ("每月", "monthly")
        ]

        for text, value in repeat_options:
            ttk.Radiobutton(repeat_type_frame, text=text, variable=self.repeat_type,
                            value=value).pack(side=tk.LEFT, padx=10)

        # 设置提醒按钮
        self.repeat_set_button = ttk.Button(self.repeat_frame, text="设置重复提醒",
                                            command=self.set_repeat_reminder)
        self.repeat_set_button.pack(pady=10)

    def show_reminder(self, message, reminder_id):
        # 如果启用了声音,播放提示音
        if self.sound_enabled.get():
            sound_thread = threading.Thread(target=play_alert)
            sound_thread.start()

        # 显示消息框
        messagebox.showinfo("提醒", message)

        # 如果是单次提醒,显示后删除
        if reminder_id in self.reminders and not self.reminders[reminder_id].get('repeat'):
            self.remove_reminder(reminder_id)
            self.update_reminder_list()

    def test_sound(self):
        """测试提醒声音"""
        if self.sound_enabled.get():
            play_alert()

    def set_single_reminder(self):
        date_str = self.date_entry.get()
        time_str = self.single_time_entry.get()
        message = self.single_message_entry.get()

        if not all([date_str, time_str, message]):
            messagebox.showerror("错误", "请填写所有字段")
            return

        try:
            reminder_datetime = datetime.strptime(f"{date_str} {time_str}", "%Y-%m-%d %H:%M")
            if reminder_datetime < datetime.now():
                messagebox.showerror("错误", "不能设置过去的时间")
                return

            reminder_id = f"single_{len(self.reminders)}"
            delay = (reminder_datetime - datetime.now()).total_seconds()

            timer = threading.Timer(delay, self.show_reminder, args=[message, reminder_id])
            timer.start()

            self.reminders[reminder_id] = {
                'datetime': reminder_datetime,
                'message': message,
                'timer': timer,
                'repeat': False
            }

            self.update_reminder_list()
            messagebox.showinfo("成功", f"提醒已设置在 {date_str} {time_str}")

        except ValueError:
            messagebox.showerror("错误", "日期或时间格式错误")

    def set_repeat_reminder(self):
        time_str = self.repeat_time_entry.get()
        message = self.repeat_message_entry.get()
        repeat_type = self.repeat_type.get()

        if not all([time_str, message]):
            messagebox.showerror("错误", "请填写所有字段")
            return

        try:
            reminder_id = f"repeat_{len(self.reminders)}"

            if repeat_type == "daily":
                job = schedule.every().day.at(time_str).do(
                    self.show_reminder, message, reminder_id)
            elif repeat_type == "weekly":
                job = schedule.every().week.at(time_str).do(
                    self.show_reminder, message, reminder_id)
            elif repeat_type == "monthly":
                job = schedule.every().month.at(time_str).do(
                    self.show_reminder, message, reminder_id)

            self.reminders[reminder_id] = {
                'time': time_str,
                'message': message,
                'job': job,
                'repeat': True,
                'repeat_type': repeat_type
            }

            self.update_reminder_list()
            messagebox.showinfo("成功", f"重复提醒已设置")

        except schedule.ScheduleValueError:
            messagebox.showerror("错误", "时间格式错误,请使用HH:MM格式")

    def delete_reminder(self):
        selection = self.reminder_list.curselection()
        if not selection:
            messagebox.showwarning("警告", "请先选择要删除的提醒")
            return

        reminder_id = list(self.reminders.keys())[selection[0]]
        self.remove_reminder(reminder_id)
        self.update_reminder_list()
        messagebox.showinfo("成功", "提醒已删除")

    def remove_reminder(self, reminder_id):
        if reminder_id in self.reminders:
            reminder = self.reminders[reminder_id]
            if reminder.get('repeat'):
                schedule.cancel_job(reminder['job'])
            else:
                reminder['timer'].cancel()
            del self.reminders[reminder_id]

    def update_reminder_list(self):
        self.reminder_list.delete(0, tk.END)
        for reminder_id, reminder in self.reminders.items():
            if reminder.get('repeat'):
                text = f"重复提醒: {reminder['time']} - {reminder['message']} ({reminder['repeat_type']})"
            else:
                text = f"单次提醒: {reminder['datetime'].strftime('%Y-%m-%d %H:%M')} - {reminder['message']}"
            self.reminder_list.insert(tk.END, text)

    def run_schedule(self):
        while True:
            schedule.run_pending()
            time.sleep(1)

    def run(self):
        self.root.mainloop()


if __name__ == "__main__":
    app = ReminderApp()
    app.run()

六、总结

脚本通过组合使用多线程、定时器、图形界面和事件调度等技术,实现一个功能完整的定时提醒系统。

七、注意事项

这个脚本仍然需要保持运行状态才能实现提醒功能。如果你需要在计算机启动时自动运行,可以将其设置为开机启动项。

<think>好的,用户需要找一个Python的重命名图片的脚本。首先,我得回忆一下相关的Python库,处理文件操作通常用os模块,处理路径可以用os.path或者pathlib。用户提到的示例中有一个重命名多个文件的脚本,引用[1]里提到了一个脚本,可以将旧名称替换为新名称,可能需要参考这个结构。 接下来,用户的需求是重命名图片,可能需要批量处理,所以脚本应该遍历目录中的文件,过滤出图片文件,比如.jpg、.png等扩展名。然后生成新的文件名,可能是按顺序编号,或者根据某些规则修改。 需要注意不同操作系统的路径问题,使用os模块的os.rename函数应该可以跨平台。另外,处理文件时最好检查目标文件名是否已存在,避免覆盖。可能还需要让用户指定目录路径、新名称的模板,比如“image_001.jpg”这样的格式。 然后,考虑用户可能的其他需求,比如保留原始扩展名,只修改文件名部分。或者根据创建日期、修改日期来重命名。不过用户的问题比较基础,可能只需要简单的批量重命名。 根据引用[1]中的示例,旧名称和新名称作为输入,但用户可能需要更自动化的方式,比如按顺序编号。所以脚本需要遍历目录中的图片文件,并按顺序重命名。 还需要处理异常情况,比如没有权限、文件不存在等,但用户可能不需要太复杂的错误处理,基础的try-except可能就够用。 最后,确保代码示例正确,使用os.listdir获取文件列表,过滤出图片文件,然后逐个重命名。可能需要使用os.path.splitext来分离文件名和扩展名,保持扩展名不变。 测试一下代码逻辑:遍历目录,过滤图片,生成新名称,然后重命名。可能需要用户输入目录路径和新名称前缀,比如“vacation_”,然后生成类似“vacation_001.jpg”的名称。 现在,把这些思路整理成一个清晰的步骤,并出代码示例。确保代码有注释,解释每一步的作用,让用户容易理解和修改。同时,提醒用户注意备份文件,防止意外错误导致数据丢失。</think>以下是根据需求编的图片批量重命名Python脚本,包含基本功能实现和扩展功能说明: ### Python图片重命名脚本 ```python import os from pathlib import Path def batch_rename_images(directory, new_name_prefix, start_num=1): """ 批量重命名目录中的图片文件 :param directory: 图片目录路径 :param new_name_prefix: 新文件名前缀(如"vacation_") :param start_num: 起始编号(默认从1开始) """ # 支持的图片扩展名列表 img_exts = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff') # 获取目录中所有图片文件 image_files = [f for f in os.listdir(directory) if f.lower().endswith(img_exts)] # 按文件名排序(可选) image_files.sort() # 执行重命名 counter = start_num for filename in image_files: # 获取文件扩展名 ext = Path(filename).suffix.lower() # 构建新文件名(格式:前缀_编号.扩展名) new_filename = f"{new_name_prefix}{counter:03d}{ext}" # 构建完整路径 old_path = os.path.join(directory, filename) new_path = os.path.join(directory, new_filename) # 执行重命名 try: os.rename(old_path, new_path) print(f"重命名成功: {filename} -> {new_filename}") counter += 1 except Exception as e: print(f"错误处理 {filename}: {str(e)}") # 使用示例 batch_rename_images( directory="/path/to/your/images", new_name_prefix="vacation_", start_num=1 ) ``` ### 功能说明 1. **基本功能**: - 自动识别常见图片格式(`.jpg`, `.png`等) - 按顺序生成编号(格式:前缀_001.jpg) - 保留原始文件扩展名 - 提供成功/错误反馈 2. **扩展功能建议**: - 添加文件属性重命名(如按创建日期) ```python from datetime import datetime # 在循环内添加: create_time = os.path.getctime(old_path) date_str = datetime.fromtimestamp(create_time).strftime("%Y%m%d") ``` - 添加文件校验功能 ```python from PIL import Image # 在循环开始前添加: try: with Image.open(old_path) as img: img.verify() except (IOError, SyntaxError) as e: print(f"损坏文件跳过: {filename}") continue ``` ### 使用注意事项 1. **路径设置**:替换`/path/to/your/images`为实际图片目录路径 2. **前缀规范**:建议使用有意义的命名前缀(如"travel_", "product_") 3. **安全建议**: - 操作前**备份原始文件** - 首次运行时建议先注释`os.rename`行,测试输出 4. 支持批量处理数万级文件(内存效率优化)[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿梭的编织者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值