零广告 | 纯本地 | 极简Windows桌面壁纸管理神器 —— 开发者的清爽编程伴侣

零广告 | 纯本地 | 极简Windows桌面壁纸管理神器 —— 开发者的清爽编程伴侣


零广告 | 纯本地 | 极简Windows桌面壁纸管理神器 —— 开发者的清爽编程伴侣_第1张图片


前言:用技术创造清爽办公环境

近期在探索AI图像生成工具时,意外打造出一系列极具清凉感的沙滩主题壁纸。适逢南方盛夏将至,作为开发者突然意识到:与其在臃肿的壁纸软件中与广告斗智斗勇,何不自建一个纯净的本地化壁纸管理方案?

本工具完美解决三大痛点:
✅ 彻底告别商业软件弹窗与隐私风险
✅ 原生支持Windows系统壁纸智能轮换
✅ 极简交互实现

在历经与DeepSeek-coder的23次"服务器繁忙"博弈后,终于打磨出这款开箱即用的解决方案,测试运行成功。现将完整源码分享给各位技术同好,助您打造清爽无扰的开发环境。

如果您觉得有帮助,有空来我的主页逛逛,欢迎关注互三!
【浩瀚星空】微博主页:https://blog.csdn.net/deepever
【浩瀚星空】近期系列文章导航:已综合近期发布的系列博文:
【PanLang 原型全栈设计方案与实验性探索】
【穿越之程序员周树人的狂人日记】


1. 安装依赖

pip install pillow pywin32 winshell

2. 主要功能

  • 更改壁纸目录:点击"更改壁纸目录"按钮选择新位置
  • 多选删除
    • Shift+左键:连续多选
    • Ctrl+左键:间隔多选
    • 右键菜单:快速删除
  • 壁纸契合度:从下拉框选择6种不同模式
  • 三种壁纸模式:选定模式、连续轮播、定时模式

3. 定时模式

  • 设置时间段会自动检查重叠
  • 可以添加多个不重叠的时间段
  • 设置默认壁纸覆盖未设置时段

4. 图片预览

  • 选择壁纸时右侧会显示预览
  • 支持常见图片格式(JPG/PNG/BMP等)

零广告 | 纯本地 | 极简Windows桌面壁纸管理神器 —— 开发者的清爽编程伴侣_第2张图片


以下是完整的壁纸设置工具代码:

import os
import shutil
import json
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk
import ctypes
import winshell
from win32com.client import Dispatch
from datetime import datetime, time
import threading
import time as time_module

class WallpaperScheduler:
    def __init__(self, root):
        self.root = root
        self.root.title("高级壁纸设置工具 V3.0")
        self.root.geometry("1000x800")
        
        # 壁纸存储目录
        self.config_file = os.path.join(os.path.expanduser('~'), 'WallpaperSetter_config.json')
        self.load_config()
        
        # 定时设置存储文件
        self.schedule_file = os.path.join(self.wallpaper_dir, 'schedules.json')
        
        # 当前模式状态
        self.current_mode = "fixed"  # fixed/slide/scheduled
        self.slide_running = False
        self.slide_thread = None
        
        # 图片预览相关
        self.preview_image = None
        self.preview_label = None
        
        # 壁纸契合度选项
        self.fit_options = {
            "填充": 10,
            "适应": 6,
            "拉伸": 2,
            "平铺": 0,
            "居中": 1,
            "跨区": 22
        }
        
        # 初始化UI
        self.setup_ui()
        
        # 加载已有定时设置
        self.schedules = self.load_schedules()
        self.update_schedule_list()
        
        # 创建桌面快捷方式(仅第一次)
        self.create_shortcut_once()
        
        # 启动壁纸检查线程
        self.start_wallpaper_checker()

    def load_config(self):
        """加载配置文件"""
        default_dir = os.path.join(os.path.expanduser('~'), 'WallpaperSetter')
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as f:
                    config = json.load(f)
                    self.wallpaper_dir = config.get('wallpaper_dir', default_dir)
                    self.wallpaper_fit = config.get('wallpaper_fit', 6)  # 默认适应
            except:
                self.wallpaper_dir = default_dir
                self.wallpaper_fit = 6
        else:
            self.wallpaper_dir = default_dir
                self.wallpaper_fit = 6
        
        os.makedirs(self.wallpaper_dir, exist_ok=True)

    def save_config(self):
        """保存配置文件"""
        config = {
            'wallpaper_dir': self.wallpaper_dir,
            'wallpaper_fit': self.wallpaper_fit
        }
        with open(self.config_file, 'w') as f:
            json.dump(config, f)

    def setup_ui(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 模式选择
        mode_frame = ttk.LabelFrame(main_frame, text="模式选择", padding="10")
        mode_frame.pack(fill=tk.X, pady=5)
        
        self.mode_var = tk.StringVar(value="fixed")
        ttk.Radiobutton(mode_frame, text="选定模式", variable=self.mode_var, 
                       value="fixed", command=self.change_mode).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(mode_frame, text="连续轮播", variable=self.mode_var, 
                       value="slide", command=self.change_mode).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(mode_frame, text="定时模式", variable=self.mode_var, 
                       value="scheduled", command=self.change_mode).pack(side=tk.LEFT, padx=5)
        
        # 壁纸管理
        manage_frame = ttk.LabelFrame(main_frame, text="壁纸管理", padding="10")
        manage_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(manage_frame, text="导入壁纸", command=self.import_wallpaper).pack(side=tk.LEFT, padx=5)
        ttk.Button(manage_frame, text="删除壁纸", command=self.delete_selected_wallpapers).pack(side=tk.LEFT, padx=5)
        ttk.Button(manage_frame, text="刷新列表", command=self.update_wallpaper_list).pack(side=tk.LEFT, padx=5)
        
        # 更改目录按钮
        ttk.Button(manage_frame, text="更改壁纸目录", command=self.change_wallpaper_dir).pack(side=tk.RIGHT, padx=5)
        
        # 壁纸契合度选择
        ttk.Label(manage_frame, text="壁纸契合度:").pack(side=tk.RIGHT, padx=(10,5))
        self.fit_var = tk.StringVar()
        self.fit_combobox = ttk.Combobox(manage_frame, textvariable=self.fit_var, 
                                       values=list(self.fit_options.keys()), state="readonly", width=8)
        self.fit_combobox.pack(side=tk.RIGHT)
        self.fit_combobox.set(next(key for key, val in self.fit_options.items() if val == self.wallpaper_fit))
        self.fit_combobox.bind("<>", self.change_fit_style)
        
        # 壁纸列表和预览
        list_preview_frame = ttk.Frame(main_frame)
        list_preview_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 壁纸列表框架
        list_frame = ttk.Frame(list_preview_frame)
        list_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        self.wallpaper_list = tk.Listbox(list_frame, selectmode=tk.EXTENDED)
        self.wallpaper_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.wallpaper_list.bind('<>', self.show_preview)
        
        # 右键菜单
        self.listbox_menu = tk.Menu(self.root, tearoff=0)
        self.listbox_menu.add_command(label="删除选中壁纸", command=self.delete_selected_wallpapers)
        self.wallpaper_list.bind("", self.show_listbox_menu)
        
        scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=self.wallpaper_list.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.wallpaper_list.config(yscrollcommand=scrollbar.set)
        
        # 图片预览框架
        preview_frame = ttk.LabelFrame(list_preview_frame, text="图片预览", width=350, height=350)
        preview_frame.pack(side=tk.RIGHT, fill=tk.BOTH, padx=5)
        preview_frame.pack_propagate(False)
        
        self.preview_label = ttk.Label(preview_frame)
        self.preview_label.pack(fill=tk.BOTH, expand=True)
        
        self.update_wallpaper_list()
        
        # 选定模式设置
        self.fixed_frame = ttk.LabelFrame(main_frame, text="选定模式设置", padding="10")
        ttk.Button(self.fixed_frame, text="设置当前壁纸", command=self.set_fixed_wallpaper).pack(pady=5)
        
        # 轮播模式设置
        self.slide_frame = ttk.LabelFrame(main_frame, text="连续轮播设置", padding="10")
        ttk.Label(self.slide_frame, text="轮播间隔(秒):").pack(side=tk.LEFT)
        self.interval_entry = ttk.Entry(self.slide_frame, width=10)
        self.interval_entry.insert(0, "300")
        self.interval_entry.pack(side=tk.LEFT, padx=5)
        ttk.Button(self.slide_frame, text="开始轮播", command=self.start_slideshow).pack(side=tk.LEFT, padx=5)
        ttk.Button(self.slide_frame, text="暂停轮播", command=self.stop_slideshow).pack(side=tk.LEFT, padx=5)
        
        # 定时模式设置
        self.schedule_frame = ttk.LabelFrame(main_frame, text="定时模式设置", padding="10")
        
        # 时间选择
        time_frame = ttk.Frame(self.schedule_frame)
        time_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(time_frame, text="开始时间:").pack(side=tk.LEFT)
        self.start_hour = ttk.Spinbox(time_frame, from_=0, to=23, width=2, format="%02.0f")
        self.start_hour.set("08")
        self.start_hour.pack(side=tk.LEFT)
        ttk.Label(time_frame, text=":").pack(side=tk.LEFT)
        self.start_min = ttk.Spinbox(time_frame, from_=0, to=59, width=2, format="%02.0f")
        self.start_min.set("00")
        self.start_min.pack(side=tk.LEFT)
        
        ttk.Label(time_frame, text="结束时间:").pack(side=tk.LEFT, padx=(10,0))
        self.end_hour = ttk.Spinbox(time_frame, from_=0, to=23, width=2, format="%02.0f")
        self.end_hour.set("17")
        self.end_hour.pack(side=tk.LEFT)
        ttk.Label(time_frame, text=":").pack(side=tk.LEFT)
        self.end_min = ttk.Spinbox(time_frame, from_=0, to=59, width=2, format="%02.0f")
        self.end_min.set("00")
        self.end_min.pack(side=tk.LEFT)
        
        ttk.Button(time_frame, text="添加定时", command=self.add_schedule).pack(side=tk.LEFT, padx=10)
        
        # 默认壁纸设置
        default_frame = ttk.Frame(self.schedule_frame)
        default_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(default_frame, text="默认壁纸:").pack(side=tk.LEFT)
        self.default_wallpaper_btn = ttk.Button(default_frame, text="选择默认壁纸", 
                                              command=self.select_default_wallpaper)
        self.default_wallpaper_btn.pack(side=tk.LEFT, padx=5)
        self.default_wallpaper_label = ttk.Label(default_frame, text="未设置")
        self.default_wallpaper_label.pack(side=tk.LEFT)
        
        # 定时列表
        schedule_list_frame = ttk.Frame(self.schedule_frame)
        schedule_list_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.schedule_list = tk.Listbox(schedule_list_frame, height=5)
        self.schedule_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(schedule_list_frame, orient="vertical", command=self.schedule_list.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.schedule_list.config(yscrollcommand=scrollbar.set)
        
        # 定时操作按钮
        btn_frame = ttk.Frame(self.schedule_frame)
        btn_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(btn_frame, text="删除选中定时", command=self.remove_schedule).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="清空所有定时", command=self.clear_all_schedules).pack(side=tk.LEFT, padx=5)
        
        # 初始显示选定模式
        self.fixed_frame.pack(fill=tk.X, pady=5)
        
        # 底部状态栏
        self.status_var = tk.StringVar()
        self.status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN)
        self.status_bar.pack(fill=tk.X, pady=(10,0))
        
        self.update_status("准备就绪")

    def change_wallpaper_dir(self):
        new_dir = filedialog.askdirectory(initialdir=self.wallpaper_dir)
        if new_dir:
            # 移动现有壁纸到新目录
            try:
                for file in os.listdir(self.wallpaper_dir):
                    if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
                        shutil.move(os.path.join(self.wallpaper_dir, file), os.path.join(new_dir, file))
                
                # 更新目录设置
                self.wallpaper_dir = new_dir
                self.save_config()
                self.update_wallpaper_list()
                self.update_status(f"壁纸目录已更改为: {new_dir}")
            except Exception as e:
                messagebox.showerror("错误", f"更改目录失败: {e}")

    def show_listbox_menu(self, event):
        """显示右键菜单"""
        try:
            self.listbox_menu.tk_popup(event.x_root, event.y_root)
        finally:
            self.listbox_menu.grab_release()

    def delete_selected_wallpapers(self):
        """删除选中的壁纸(支持多选)"""
        selected = self.wallpaper_list.curselection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的壁纸!")
            return
            
        if not messagebox.askyesno("确认", f"确定要删除选中的 {len(selected)} 张壁纸吗?"):
            return
            
        success = 0
        for i in reversed(selected):  # 从后往前删除避免索引变化
            image_path = self.wallpaper_list.get(i)
            try:
                os.remove(image_path)
                self.wallpaper_list.delete(i)
                success += 1
            except Exception as e:
                self.update_status(f"删除 {os.path.basename(image_path)} 失败: {e}")
        
        self.update_status(f"已删除 {success}/{len(selected)} 张壁纸")
        self.preview_label.config(image=None)
        self.preview_image = None

    def change_fit_style(self, event=None):
        """更改壁纸契合度"""
        fit_name = self.fit_var.get()
        self.wallpaper_fit = self.fit_options.get(fit_name, 6)
        self.save_config()
        
        # 立即应用新设置
        if self.current_mode == "fixed" and hasattr(self, 'current_fixed_wallpaper'):
            self.set_wallpaper(self.current_fixed_wallpaper)
        elif self.current_mode == "slide" and self.slide_running:
            self.set_wallpaper(self.slide_wallpapers[self.slide_index - 1])
        elif self.current_mode == "scheduled":
            self.check_and_apply_wallpaper()
        
        self.update_status(f"壁纸契合度已设置为: {fit_name}")

    def set_wallpaper(self, path):
        try:
            if not os.path.exists(path):
                self.update_status(f"错误: 壁纸文件不存在 - {path}")
                return False
                
            # 设置壁纸和契合度
            ctypes.windll.user32.SystemParametersInfoW(20, 0, path, 3)
            ctypes.windll.user32.SystemParametersInfoW(20, 0, path, self.wallpaper_fit | 0x0010)
            self.update_status(f"壁纸已设置为: {os.path.basename(path)}")
            return True
        except Exception as e:
            self.update_status(f"设置壁纸时出错: {e}")
            return False

    def show_preview(self, event):
        selected = self.wallpaper_list.curselection()
        if not selected:
            return
            
        image_path = self.wallpaper_list.get(selected[0])
        
        try:
            # 加载图片并调整大小以适应预览区域
            img = Image.open(image_path)
            img.thumbnail((350, 350))
            
            # 更新预览
            self.preview_image = ImageTk.PhotoImage(img)
            self.preview_label.config(image=self.preview_image)
        except Exception as e:
            self.update_status(f"预览图片失败: {e}")

    def import_wallpaper(self):
        files = filedialog.askopenfilenames(
            filetypes=[("图片文件", "*.jpg;*.jpeg;*.png;*.bmp")])
        
        if files:
            success = 0
            for file in files:
                try:
                    # 自动重命名避免重复
                    basename = os.path.basename(file)
                    name, ext = os.path.splitext(basename)
                    counter = 1
                    new_name = f"{name}{ext}"
                    
                    while os.path.exists(os.path.join(self.wallpaper_dir, new_name)):
                        new_name = f"{name}_{counter}{ext}"
                        counter += 1
                    
                    dest = os.path.join(self.wallpaper_dir, new_name)
                    shutil.copy2(file, dest)
                    success += 1
                except Exception as e:
                    self.update_status(f"导入 {os.path.basename(file)} 失败: {e}")
            
            self.update_wallpaper_list()
            self.update_status(f"成功导入 {success}/{len(files)} 张壁纸")

    def update_wallpaper_list(self):
        self.wallpaper_list.delete(0, tk.END)
        for file in sorted(os.listdir(self.wallpaper_dir)):
            if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
                self.wallpaper_list.insert(tk.END, os.path.join(self.wallpaper_dir, file))

    def change_mode(self):
        mode = self.mode_var.get()
        self.current_mode = mode
        
        # 隐藏所有设置面板
        self.fixed_frame.pack_forget()
        self.slide_frame.pack_forget()
        self.schedule_frame.pack_forget()
        
        # 停止当前轮播
        if self.slide_running:
            self.stop_slideshow()
        
        # 显示对应设置面板
        if mode == "fixed":
            self.fixed_frame.pack(fill=tk.X, pady=5)
            self.update_status("已切换到选定模式")
        elif mode == "slide":
            self.slide_frame.pack(fill=tk.X, pady=5)
            self.update_status("已切换到连续轮播模式")
        elif mode == "scheduled":
            self.schedule_frame.pack(fill=tk.X, pady=5)
            self.update_status("已切换到定时模式")
        
        # 立即应用新模式
        self.check_and_apply_wallpaper()

    def set_fixed_wallpaper(self):
        selected = self.wallpaper_list.curselection()
        if not selected:
            messagebox.showwarning("警告", "请先选择一张壁纸!")
            return
            
        self.current_fixed_wallpaper = self.wallpaper_list.get(selected[0])
        self.set_wallpaper(self.current_fixed_wallpaper)

    def start_slideshow(self):
        if self.slide_running:
            return
            
        try:
            interval = int(self.interval_entry.get())
            if interval <= 0:
                raise ValueError
        except ValueError:
            messagebox.showerror("错误", "请输入有效的轮播间隔(正整数)")
            return
            
        wallpapers = [self.wallpaper_list.get(i) for i in range(self.wallpaper_list.size())]
        if not wallpapers:
            messagebox.showwarning("警告", "没有可用的壁纸!")
            return
            
        self.slide_running = True
        self.slide_index = 0
        self.slide_wallpapers = wallpapers
        self.slide_interval = interval
        
        self.slide_thread = threading.Thread(target=self.slide_worker, daemon=True)
        self.slide_thread.start()
        
        self.update_status(f"开始轮播壁纸,间隔 {interval} 秒")

    def slide_worker(self):
        while self.slide_running:
            if self.slide_index >= len(self.slide_wallpapers):
                self.slide_index = 0
                
            wallpaper = self.slide_wallpapers[self.slide_index]
            self.root.after(0, lambda: self.set_wallpaper(wallpaper))
            
            self.slide_index += 1
            time_module.sleep(self.slide_interval)

    def stop_slideshow(self):
        if self.slide_running:
            self.slide_running = False
            if self.slide_thread and self.slide_thread.is_alive():
                self.slide_thread.join(timeout=1)
            self.update_status("已停止轮播")

    def add_schedule(self):
        selected = self.wallpaper_list.curselection()
        if not selected:
            messagebox.showwarning("警告", "请先选择一张壁纸!")
            return
            
        try:
            start_h = int(self.start_hour.get())
            start_m = int(self.start_min.get())
            end_h = int(self.end_hour.get())
            end_m = int(self.end_min.get())
            
            if not (0 <= start_h <= 23 and 0 <= start_m <= 59 and
                    0 <= end_h <= 23 and 0 <= end_m <= 59):
                raise ValueError
                
            start_time = time(start_h, start_m)
            end_time = time(end_h, end_m)
            
            if start_time >= end_time:
                messagebox.showwarning("警告", "结束时间必须晚于开始时间!")
                return
                
            # 检查时间重叠
            if self.check_schedule_overlap(start_time, end_time):
                messagebox.showwarning("警告", "时间段与其他定时重叠,请调整时间!")
                return
                
        except ValueError:
            messagebox.showerror("错误", "请输入有效的时间!")
            return
            
        wallpaper = self.wallpaper_list.get(selected[0])
        
        schedule_id = max([s['id'] for s in self.schedules], default=0) + 1
        new_schedule = {
            'id': schedule_id,
            'start': f"{start_h:02d}:{start_m:02d}",
            'end': f"{end_h:02d}:{end_m:02d}",
            'wallpaper': wallpaper
        }
        
        self.schedules.append(new_schedule)
        self.save_schedules()
        self.update_schedule_list()
        self.update_status(f"已添加定时: {self.start_hour.get()}:{self.start_min.get()} - {self.end_hour.get()}:{self.end_min.get()}")

    def check_schedule_overlap(self, new_start, new_end):
        """检查新时间段是否与已有定时重叠"""
        for schedule in self.schedules:
            existing_start = datetime.strptime(schedule['start'], "%H:%M").time()
            existing_end = datetime.strptime(schedule['end'], "%H:%M").time()
            
            # 检查时间段重叠的四种情况
            if (new_start < existing_end and new_end > existing_start):
                return True
        return False

    def remove_schedule(self):
        selected = self.schedule_list.curselection()
        if not selected:
            messagebox.showwarning("警告", "请先选择一个定时!")
            return
            
        # 获取选中的定时ID
        selected_text = self.schedule_list.get(selected[0])
        schedule_id = int(selected_text.split("ID:")[1].split(")")[0])
        
        # 从列表中移除
        self.schedules = [s for s in self.schedules if s['id'] != schedule_id]
        self.save_schedules()
        self.update_schedule_list()
        self.update_status(f"已删除定时 ID: {schedule_id}")

    def clear_all_schedules(self):
        if messagebox.askyesno("确认", "确定要清空所有定时设置吗?"):
            self.schedules = []
            self.save_schedules()
            self.update_schedule_list()
            self.update_status("已清空所有定时设置")

    def select_default_wallpaper(self):
        selected = self.wallpaper_list.curselection()
        if not selected:
            messagebox.showwarning("警告", "请先选择一张壁纸!")
            return
            
        self.default_wallpaper = self.wallpaper_list.get(selected[0])
        self.default_wallpaper_label.config(text=os.path.basename(self.default_wallpaper))
        self.save_schedules()
        self.update_status(f"已设置默认壁纸: {os.path.basename(self.default_wallpaper)}")

    def update_schedule_list(self):
        self.schedule_list.delete(0, tk.END)
        for s in sorted(self.schedules, key=lambda x: x['start']):
            self.schedule_list.insert(tk.END, 
                f"ID:{s['id']}) {s['start']} - {s['end']}: {os.path.basename(s['wallpaper'])}")

    def load_schedules(self):
        if os.path.exists(self.schedule_file):
            try:
                with open(self.schedule_file, 'r') as f:
                    data = json.load(f)
                    self.default_wallpaper = data.get('default_wallpaper', '')
                    if self.default_wallpaper:
                        self.default_wallpaper_label.config(text=os.path.basename(self.default_wallpaper))
                    return data.get('schedules', [])
            except:
                pass
        return []

    def save_schedules(self):
        data = {
            'schedules': self.schedules,
            'default_wallpaper': getattr(self, 'default_wallpaper', '')
        }
        with open(self.schedule_file, 'w') as f:
            json.dump(data, f)

    def start_wallpaper_checker(self):
        self.checker_running = True
        self.checker_thread = threading.Thread(target=self.wallpaper_checker, daemon=True)
        self.checker_thread.start()

    def wallpaper_checker(self):
        while self.checker_running:
            self.check_and_apply_wallpaper()
            time_module.sleep(60)  # 每分钟检查一次

    def check_and_apply_wallpaper(self):
        if self.current_mode == "fixed":
            if hasattr(self, 'current_fixed_wallpaper'):
                self.set_wallpaper(self.current_fixed_wallpaper)
        elif self.current_mode == "slide":
            pass  # 轮播由单独线程处理
        elif self.current_mode == "scheduled":
            now = datetime.now().time()
            current_schedule = None
            
            for schedule in self.schedules:
                start = datetime.strptime(schedule['start'], "%H:%M").time()
                end = datetime.strptime(schedule['end'], "%H:%M").time()
                
                if start <= now <= end:
                    current_schedule = schedule
                    break
                    
            if current_schedule:
                self.set_wallpaper(current_schedule['wallpaper'])
            elif hasattr(self, 'default_wallpaper') and self.default_wallpaper:
                self.set_wallpaper(self.default_wallpaper)

    def create_shortcut_once(self):
        shortcut_path = os.path.join(winshell.desktop(), "壁纸设置工具.lnk")
        if not os.path.exists(shortcut_path):
            try:
                shell = Dispatch('WScript.Shell')
                shortcut = shell.CreateShortCut(shortcut_path)
                shortcut.TargetPath = os.path.abspath(__file__)
                shortcut.WorkingDirectory = os.path.dirname(os.path.abspath(__file__))
                shortcut.IconLocation = os.path.abspath(__file__)
                shortcut.save()
                self.update_status("已在桌面创建快捷方式")
            except Exception as e:
                self.update_status(f"创建快捷方式失败: {e}")

    def update_status(self, message):
        self.status_var.set(message)
        self.root.update()

    def on_closing(self):
        self.checker_running = False
        if self.slide_running:
            self.stop_slideshow()
        if self.checker_thread and self.checker_thread.is_alive():
            self.checker_thread.join(timeout=1)
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    try:
        # 检查Pillow库是否安装
        from PIL import Image, ImageTk
    except ImportError:
        messagebox.showerror("错误", "需要安装Pillow库以支持图片预览功能\n请运行: pip install pillow")
        root.destroy()
    else:
        app = WallpaperScheduler(root)
        root.protocol("WM_DELETE_WINDOW", app.on_closing)
        root.mainloop()

你可能感兴趣的:(windows,python,visual,studio,人工智能,学习方法,程序人生,经验分享)