开源代码(为了防止被误认为打广告,API相关代码和网址不开源)
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import requests
import os
import time
import threading
import ctypes
from PIL import Image, ImageTk, ImageDraw, ImageFont
import io
import sys
import pystray
from pystray import MenuItem as item
import winshell
from win32com.client import Dispatch
import webbrowser
import hashlib
import glob
import shutil
class SplashScreen:
def __init__(self, root, main_app):
self.root = root
self.main_app = main_app
self.splash = tk.Toplevel(root)
self.splash.title("壁纸更换工具")
self.splash.geometry("400x300")
self.splash.overrideredirect(True)
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = (screen_width - 400) // 2
y = (screen_height - 300) // 2
self.splash.geometry(f"400x300+{x}+{y}")
self.splash.configure(bg="#2c3e50")
self.create_content()
self.splash.after(2000, self.close_splash)
def create_content(self):
title_label = tk.Label(self.splash, text="壁纸更换工具",
font=("微软雅黑", 24, "bold"),
fg="#ecf0f1", bg="#2c3e50")
title_label.pack(pady=40)
subtitle_label = tk.Label(self.splash, text="Wallpaper Changer",
font=("微软雅黑", 12),
fg="#bdc3c7", bg="#2c3e50")
subtitle_label.pack(pady=10)
self.progress = ttk.Progressbar(self.splash, mode='indeterminate', length=300)
self.progress.pack(pady=30)
self.progress.start()
version_label = tk.Label(self.splash, text="版本 1.0",
font=("微软雅黑", 8),
fg="#7f8c8d", bg="#2c3e50")
version_label.pack(side=tk.BOTTOM, pady=10)
def close_splash(self):
self.splash.destroy()
self.main_app.show_main_window()
class WallpaperCache:
def __init__(self):
self.cache_dir = "wp-52pojie"
self.max_cache_size = 100
self.api_error_shown = {}
self.setup_cache_dirs()
def setup_cache_dirs(self):
if not os.path.exists(self.cache_dir):
os.makedirs(self.cache_dir)
def get_api_cache_dir(self, api_name):
api_dir = os.path.join(self.cache_dir, api_name)
if not os.path.exists(api_dir):
os.makedirs(api_dir)
return api_dir
def calculate_image_hash(self, image_data):
return hashlib.md5(image_data).hexdigest()
def save_image_to_cache(self, api_name, image_data, image_url=None):
try:
api_dir = self.get_api_cache_dir(api_name)
image_hash = self.calculate_image_hash(image_data)
existing_files = glob.glob(os.path.join(api_dir, "*.jpg"))
existing_files.extend(glob.glob(os.path.join(api_dir, "*.png")))
for file_path in existing_files:
with open(file_path, 'rb') as f:
if self.calculate_image_hash(f.read()) == image_hash:
return file_path
timestamp = int(time.time())
filename = f"{timestamp}_{image_hash}.jpg"
filepath = os.path.join(api_dir, filename)
with open(filepath, 'wb') as f:
f.write(image_data)
self.cleanup_cache(api_name)
return filepath
except Exception as e:
print(f"保存缓存失败: {e}")
return None
def cleanup_cache(self, api_name):
try:
api_dir = self.get_api_cache_dir(api_name)
image_files = []
for ext in ['*.jpg', '*.png']:
image_files.extend(glob.glob(os.path.join(api_dir, ext)))
if len(image_files) > self.max_cache_size:
image_files.sort(key=os.path.getmtime)
files_to_delete = image_files[:len(image_files) - self.max_cache_size]
for file_path in files_to_delete:
try:
os.remove(file_path)
except:
pass
except Exception as e:
print(f"清理缓存失败: {e}")
def get_latest_cached_image(self, api_name):
try:
api_dir = self.get_api_cache_dir(api_name)
image_files = []
for ext in ['*.jpg', '*.png']:
image_files.extend(glob.glob(os.path.join(api_dir, ext)))
if not image_files:
return None
latest_file = max(image_files, key=os.path.getmtime)
return latest_file
except:
return None
def get_cached_image_count(self, api_name):
try:
api_dir = self.get_api_cache_dir(api_name)
image_files = []
for ext in ['*.jpg', '*.png']:
image_files.extend(glob.glob(os.path.join(api_dir, ext)))
return len(image_files)
except:
return 0
def clear_cache(self, api_name=None):
try:
if api_name:
api_dir = self.get_api_cache_dir(api_name)
if os.path.exists(api_dir):
shutil.rmtree(api_dir)
else:
if os.path.exists(self.cache_dir):
shutil.rmtree(self.cache_dir)
self.setup_cache_dirs()
return True
except Exception as e:
print(f"清除缓存失败: {e}")
return False
class WallpaperChanger:
def __init__(self, root):
self.root = root
self.root.title("壁纸自动更换工具")
self.root.geometry("800x700")
self.root.resizable(True, True)
self.root.configure(bg="#ecf0f1")
self.root.withdraw()
self.font_title = ("微软雅黑", 16, "bold")
self.font_subtitle = ("微软雅黑", 12, "bold")
self.font_normal = ("微软雅黑", 11)
self.font_small = ("微软雅黑", 9)
self.color_primary = "#3498db"
self.color_secondary = "#2ecc71"
self.color_danger = "#e74c3c"
self.color_warning = "#f39c12"
self.color_dark = "#2c3e50"
self.color_light = "#ecf0f1"
self.cache = WallpaperCache()
self.setup_styles()
self.current_api = tk.StringVar(value="bing")
self.refresh_interval = tk.IntVar(value=60)
self.auto_start = tk.BooleanVar(value=False)
self.is_running = False
self.timer_thread = None
self.tray_icon = None
self.apis = {
此处为API列表,为了防止被误认广告已删除
}
self.custom_apis = {}
self.log_messages = []
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
self.create_main_tab()
self.create_settings_tab()
self.create_about_tab()
self.root.protocol('WM_DELETE_WINDOW', self.minimize_to_tray)
self.check_auto_start()
self.splash = SplashScreen(self.root, self)
def show_main_window(self):
self.root.update()
width = 800
height = 700
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
x = (screen_width - width) // 2
y = (screen_height - height) // 2
self.root.geometry(f"{width}x{height}+{x}+{y}")
self.root.deiconify()
def setup_styles(self):
style = ttk.Style()
style.configure("TNotebook", background=self.color_light)
style.configure("TNotebook.Tab", font=self.font_subtitle, padding=[10, 5])
style.configure("Primary.TButton", font=self.font_normal, background=self.color_primary, padding=10)
style.configure("Success.TButton", font=self.font_normal, background=self.color_secondary, padding=10)
style.configure("Danger.TButton", font=self.font_normal, background=self.color_danger, padding=10)
style.configure("Warning.TButton", font=self.font_normal, background=self.color_warning, padding=10)
style.configure("TLabelframe", background=self.color_light)
style.configure("TLabelframe.Label", font=self.font_subtitle, background=self.color_light)
style.configure("TLabel", background=self.color_light, font=self.font_normal)
style.configure("TRadiobutton", background=self.color_light, font=self.font_normal)
style.configure("TCheckbutton", background=self.color_light, font=self.font_normal)
def create_main_tab(self):
self.main_frame = ttk.Frame(self.notebook, padding="15")
self.notebook.add(self.main_frame, text="壁纸更换")
api_frame = ttk.LabelFrame(self.main_frame, text="选择壁纸源", padding="10")
api_frame.pack(fill=tk.X, pady=10)
api_buttons_frame = ttk.Frame(api_frame)
api_buttons_frame.pack(fill=tk.X, pady=5)
for i, (api_key, api_info) in enumerate(self.apis.items()):
ttk.Radiobutton(api_buttons_frame, text=api_info["name"], variable=self.current_api,
value=api_key, command=self.load_preview_image).grid(row=0, column=i, sticky=tk.W, padx=10)
custom_frame = ttk.Frame(api_buttons_frame)
custom_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5)
ttk.Radiobutton(custom_frame, text="自定义API", variable=self.current_api,
value="custom", command=self.load_preview_image).grid(row=0, column=0, sticky=tk.W)
ttk.Button(custom_frame, text="管理自定义API",
command=self.manage_custom_apis, style="Primary.TButton").grid(row=0, column=1, padx=10)
preview_frame = ttk.LabelFrame(self.main_frame, text="壁纸预览", padding="10")
preview_frame.pack(fill=tk.BOTH, expand=True, pady=10)
self.preview_label = ttk.Label(preview_frame, text="点击刷新预览...", font=self.font_normal)
self.preview_label.pack(expand=True, fill=tk.BOTH, pady=20)
self.preview_label.bind("[B]", lambda e: self.load_preview_image())
control_frame = ttk.LabelFrame(self.main_frame, text="控制设置", padding="10")
control_frame.pack(fill=tk.X, pady=10)
interval_frame = ttk.Frame(control_frame)
interval_frame.pack(fill=tk.X, pady=5)
ttk.Label(interval_frame, text="更换间隔(分钟):", font=self.font_normal).grid(row=0, column=0, sticky=tk.W)
scale_input_frame = ttk.Frame(interval_frame)
scale_input_frame.grid(row=0, column=1, sticky=(tk.W, tk.E))
ttk.Scale(scale_input_frame, from_=1, to=240, variable=self.refresh_interval,
orient=tk.HORIZONTAL, length=200).grid(row=0, column=0, padx=10)
self.interval_entry = ttk.Entry(scale_input_frame, width=5, font=self.font_normal)
self.interval_entry.grid(row=0, column=1, padx=5)
self.interval_entry.insert(0, "60")
self.interval_entry.bind("", self.update_interval_from_entry)
ttk.Label(scale_input_frame, textvariable=self.refresh_interval, font=self.font_normal).grid(row=0, column=2, padx=5)
cache_frame = ttk.Frame(interval_frame)
cache_frame.grid(row=1, column=0, columnspan=3, sticky=tk.W, pady=5)
ttk.Button(cache_frame, text="清理缓存",
command=self.clear_cache, style="Warning.TButton").grid(row=0, column=0, padx=5)
self.cache_info_label = ttk.Label(cache_frame, text="", font=self.font_small)
self.cache_info_label.grid(row=0, column=1, padx=10)
button_frame = ttk.Frame(control_frame)
button_frame.pack(fill=tk.X, pady=10)
ttk.Button(button_frame, text="立即更换壁纸",
command=self.apply_wallpaper, style="Primary.TButton").grid(row=0, column=0, padx=10, ipadx=10)
ttk.Button(button_frame, text="开始自动更换",
command=self.start_auto_change, style="Success.TButton").grid(row=0, column=1, padx=10, ipadx=10)
ttk.Button(button_frame, text="停止自动更换",
command=self.stop_auto_change, style="Danger.TButton").grid(row=0, column=2, padx=10, ipadx=10)
ttk.Button(button_frame, text="恢复默认壁纸",
command=self.restore_default_wallpaper, style="Warning.TButton").grid(row=0, column=3, padx=10, ipadx=10)
log_frame = ttk.LabelFrame(self.main_frame, text="操作日志", padding="10")
log_frame.pack(fill=tk.BOTH, expand=True, pady=10)
self.log_text = tk.Text(log_frame, wrap=tk.WORD, font=self.font_small, height=8)
scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
self.log_text.configure(yscrollcommand=scrollbar.set)
self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.log("程序启动完成")
self.update_cache_info()
interval_frame.columnconfigure(1, weight=1)
def create_settings_tab(self):
self.settings_frame = ttk.Frame(self.notebook, padding="15")
self.notebook.add(self.settings_frame, text="设置")
system_frame = ttk.LabelFrame(self.settings_frame, text="系统设置", padding="10")
system_frame.pack(fill=tk.X, pady=10)
ttk.Checkbutton(system_frame, text="开机自启动",
variable=self.auto_start, command=self.toggle_auto_start).grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Button(system_frame, text="最小化到托盘",
command=self.minimize_to_tray, style="Primary.TButton").grid(row=0, column=1, padx=20, pady=5, ipadx=10)
cache_settings_frame = ttk.LabelFrame(self.settings_frame, text="缓存设置", padding="10")
cache_settings_frame.pack(fill=tk.X, pady=10)
ttk.Label(cache_settings_frame, text="最大缓存数量:", font=self.font_normal).grid(row=0, column=0, sticky=tk.W)
self.max_cache_var = tk.StringVar(value=str(self.cache.max_cache_size))
max_cache_entry = ttk.Entry(cache_settings_frame, textvariable=self.max_cache_var, width=10, font=self.font_normal)
max_cache_entry.grid(row=0, column=1, padx=10)
max_cache_entry.bind("", self.update_max_cache)
ttk.Button(cache_settings_frame, text="应用",
command=self.update_max_cache, style="Primary.TButton").grid(row=0, column=2, padx=5)
help_frame = ttk.LabelFrame(self.settings_frame, text="使用说明", padding="10")
help_frame.pack(fill=tk.BOTH, expand=True, pady=10)
help_text = """
使用说明:
1. 选择壁纸源:
- 必应每日壁纸:每天更新的必应精美壁纸(大量)
- 原神官图:原神官方发布的精美图片(中等数量)
- NASA天文图片:NASA提供的天文图片(少量)
- 其他API:上方未列出的API寻找自网络,任何标注(非作者API)的API作者只进行了几轮检查,不保证所有图片适宜且图片内容与作者无关
- 自定义API:使用您自己的图片API
2. 设置更换间隔:
- 使用滑块或直接输入分钟数
- 最小1分钟,最大240分钟(4小时)
3. 控制功能:
- 立即更换壁纸:手动更换当前壁纸
- 开始自动更换:按照设定间隔自动更换壁纸
- 停止自动更换:停止自动更换功能
- 恢复默认壁纸:恢复系统默认壁纸
4. 缓存功能:
- 自动保存下载的壁纸到缓存
- 避免重复下载相同图片
- API失败时自动使用缓存图片
- 可设置最大缓存数量
5. 系统设置:
- 开机自启动:程序随系统启动
- 最小化到托盘:关闭窗口时最小化到系统托盘
6. 托盘操作:
- 右键点击托盘图标可显示菜单
- 支持快速更换壁纸和退出程序
"""
help_label = tk.Text(help_frame, wrap=tk.WORD, font=self.font_normal, bg=self.color_light,
relief=tk.FLAT, height=15)
help_label.pack(fill=tk.BOTH, expand=True)
help_label.insert(tk.END, help_text)
help_label.config(state=tk.DISABLED)
def create_about_tab(self):
self.about_frame = ttk.Frame(self.notebook, padding="15")
self.notebook.add(self.about_frame, text="关于")
info_frame = ttk.LabelFrame(self.about_frame, text="程序信息", padding="10")
info_frame.pack(fill=tk.X, pady=10)
info_text = """
壁纸自动更换工具
版本: 1.0
作者: 52pojie_Skyeath1
发布日期: 2025年
郑重声明:本页面提供的所有API均不保证可用性
"""
info_label = tk.Text(info_frame, wrap=tk.WORD, font=self.font_normal, bg=self.color_light,
relief=tk.FLAT, height=10)
info_label.pack(fill=tk.BOTH, expand=True)
info_label.insert(tk.END, info_text)
info_label.config(state=tk.DISABLED)
contact_frame = ttk.LabelFrame(self.about_frame, text="联系信息", padding="10")
contact_frame.pack(fill=tk.X, pady=10)
contact_text = """
如果您在使用过程中遇到任何问题或有任何建议,请通过以下方式联系我们:
吾爱破解论坛:https://www.52pojie.cn/home.php?mod=space&uid=2344986
"""
contact_label = tk.Text(contact_frame, wrap=tk.WORD, font=self.font_normal, bg=self.color_light,
relief=tk.FLAT, height=6)
contact_label.pack(fill=tk.BOTH, expand=True)
contact_label.insert(tk.END, contact_text)
contact_label.config(state=tk.DISABLED)
button_frame = ttk.Frame(self.about_frame)
button_frame.pack(fill=tk.X, pady=10)
ttk.Button(button_frame, text="访问",
command=lambda: webbrowser.open("https://www.52pojie.cn/home.php?mod=space&uid=2344986"),
style="Primary.TButton").pack(side=tk.LEFT, padx=10, ipadx=10)
def update_cache_info(self):
api_name = self.get_current_api_name()
count = self.cache.get_cached_image_count(api_name)
self.cache_info_label.config(text=f"当前API缓存: {count}张图片")
def update_max_cache(self, event=None):
try:
new_size = int(self.max_cache_var.get())
if new_size 100:
self.log_messages.pop(0)
self.log_text.delete(1.0, tk.END)
for msg in self.log_messages[-20:]:
self.log_text.insert(tk.END, msg + "\n")
self.log_text.see(tk.END)
def update_interval_from_entry(self, event=None):
try:
interval = int(self.interval_entry.get())
if 1 1 and frame_height > 1:
image.thumbnail((frame_width - 20, frame_height - 20), Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(image)
self.preview_label.configure(image=photo)
self.preview_label.image = photo
except Exception as e:
self.preview_label.configure(text="预览加载失败")
def apply_wallpaper(self):
threading.Thread(target=self._apply_wallpaper_thread, daemon=True).start()
def _apply_wallpaper_thread(self):
try:
self.log("正在获取壁纸...")
api_url = self.get_current_api_url()
api_name = self.get_current_api_name()
try:
response = requests.get(api_url, timeout=10)
if response.status_code == 200:
image_data = response.content
cached_path = self.cache.save_image_to_cache(api_name, image_data, api_url)
if cached_path:
self.log(f"图片已保存到缓存: {os.path.basename(cached_path)}")
temp_path = os.path.join(os.environ['TEMP'], 'wallpaper.jpg')
with open(temp_path, 'wb') as f:
f.write(image_data)
self._set_wallpaper(temp_path)
self.root.after(0, lambda: self.log("壁纸设置成功"))
self.root.after(0, self.update_cache_info)
if api_name in self.cache.api_error_shown:
del self.cache.api_error_shown[api_name]
else:
raise Exception(f"API返回状态码: {response.status_code}")
except Exception as api_error:
self.log(f"API请求失败: {str(api_error)}")
cached_image = self.cache.get_latest_cached_image(api_name)
if cached_image:
self.log("使用缓存中的图片")
self._set_wallpaper(cached_image)
self.root.after(0, lambda: self.log("使用缓存图片设置壁纸成功"))
if api_name not in self.cache.api_error_shown:
self.root.after(0, lambda api_error=api_error: messagebox.showwarning("API错误", f"{self.current_api.get()} API无法访问,已使用缓存中的图片。\n错误信息: {str(api_error)}"))
self.cache.api_error_shown[api_name] = True
else:
self.root.after(0, lambda: self.log("错误: API无法访问且无缓存图片可用"))
self.root.after(0, lambda: messagebox.showerror("错误",
f"{self.current_api.get()} API无法访问且无缓存图片可用。\n错误信息: {str(api_error)}"))
except Exception as e:
error_msg = str(e)
self.root.after(0, lambda msg=error_msg: self.log(f"错误: {msg}"))
def _set_wallpaper(self, image_path):
try:
ctypes.windll.user32.SystemParametersInfoW(20, 0, image_path, 3)
except Exception as e:
messagebox.showerror("错误", f"设置壁纸失败: {str(e)}")
def start_auto_change(self):
if not self.is_running:
self.is_running = True
self.timer_thread = threading.Thread(target=self._auto_change_loop, daemon=True)
self.timer_thread.start()
self.log("自动更换已启动")
def stop_auto_change(self):
self.is_running = False
self.log("自动更换已停止")
def _auto_change_loop(self):
while self.is_running:
self.apply_wallpaper()
time.sleep(self.refresh_interval.get() * 60)
def restore_default_wallpaper(self):
try:
ctypes.windll.user32.SystemParametersInfoW(20, 0, "", 3)
self.log("已恢复默认壁纸")
except Exception as e:
messagebox.showerror("错误", f"恢复默认壁纸失败: {str(e)}")
def check_auto_start(self):
try:
startup_path = winshell.startup()
shortcut_path = os.path.join(startup_path, "WallpaperChanger.lnk")
if os.path.exists(shortcut_path):
self.auto_start.set(True)
except:
pass
def toggle_auto_start(self):
try:
startup_path = winshell.startup()
shortcut_path = os.path.join(startup_path, "WallpaperChanger.lnk")
if self.auto_start.get():
target_path = sys.executable
wd = os.path.dirname(os.path.abspath(__file__))
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(shortcut_path)
shortcut.Targetpath = target_path
shortcut.Arguments = f'"{os.path.abspath(__file__)}"'
shortcut.WorkingDirectory = wd
shortcut.save()
self.log("已设置开机自启动")
else:
if os.path.exists(shortcut_path):
os.remove(shortcut_path)
self.log("已取消开机自启动")
except Exception as e:
messagebox.showerror("错误", f"设置开机自启动失败: {str(e)}")
self.auto_start.set(not self.auto_start.get())
def minimize_to_tray(self):
self.root.withdraw()
self.create_tray_icon()
def create_tray_icon(self):
try:
image = Image.new('RGB', (64, 64), color='#3498db')
menu = (
item('显示主窗口', self.restore_from_tray),
item('立即更换壁纸', self.apply_wallpaper),
item('退出', self.quit_application)
)
self.tray_icon = pystray.Icon("wallpaper_changer", image, "壁纸更换工具", menu)
threading.Thread(target=self.tray_icon.run, daemon=True).start()
except Exception as e:
self.quit_application()
def restore_from_tray(self, icon=None, item=None):
if self.tray_icon:
self.tray_icon.stop()
self.tray_icon = None
self.root.after(0, self.root.deiconify)
def quit_application(self, icon=None, item=None):
self.stop_auto_change()
if self.tray_icon:
self.tray_icon.stop()
self.root.quit()
self.root.destroy()
def check_for_updates(self):
messagebox.showinfo("检查更新", "当前已是最新版本!")
class CustomApiDialog:
def __init__(self, parent, custom_apis, font):
self.top = tk.Toplevel(parent)
self.top.title("管理自定义API")
self.top.geometry("500x400")
self.top.resizable(False, False)
self.top.transient(parent)
self.top.grab_set()
self.custom_apis = custom_apis.copy()
self.result = None
self.font = font
self.create_widgets()
self.update_listbox()
def create_widgets(self):
main_frame = ttk.Frame(self.top, padding="15")
main_frame.pack(fill=tk.BOTH, expand=True)
list_frame = ttk.LabelFrame(main_frame, text="自定义API列表", padding="10")
list_frame.pack(fill=tk.BOTH, expand=True, pady=10)
self.listbox = tk.Listbox(list_frame, font=self.font, height=8)
self.listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=10)
ttk.Button(button_frame, text="添加API",
command=self.add_api, style="Primary.TButton").pack(side=tk.LEFT, padx=5, ipadx=5)
ttk.Button(button_frame, text="编辑API",
command=self.edit_api, style="Primary.TButton").pack(side=tk.LEFT, padx=5, ipadx=5)
ttk.Button(button_frame, text="删除API",
command=self.delete_api, style="Danger.TButton").pack(side=tk.LEFT, padx=5, ipadx=5)
bottom_frame = ttk.Frame(main_frame)
bottom_frame.pack(fill=tk.X, pady=10)
ttk.Button(bottom_frame, text="确定",
command=self.save_and_close, style="Success.TButton").pack(side=tk.RIGHT, padx=5, ipadx=10)
ttk.Button(bottom_frame, text="取消",
command=self.cancel, style="Primary.TButton").pack(side=tk.RIGHT, padx=5, ipadx=10)
def update_listbox(self):
self.listbox.delete(0, tk.END)
for name, url in self.custom_apis.items():
self.listbox.insert(tk.END, f"{name}: {url}")
def add_api(self):
dialog = ApiDetailDialog(self.top, "", "", self.font)
self.top.wait_window(dialog.top)
if dialog.result:
name, url = dialog.result
self.custom_apis[name] = url
self.update_listbox()
def edit_api(self):
selection = self.listbox.curselection()
if not selection:
messagebox.showwarning("警告", "请先选择一个API")
return
index = selection[0]
name = list(self.custom_apis.keys())[index]
url = self.custom_apis[name]
dialog = ApiDetailDialog(self.top, name, url, self.font)
self.top.wait_window(dialog.top)
if dialog.result:
new_name, new_url = dialog.result
del self.custom_apis[name]
self.custom_apis[new_name] = new_url
self.update_listbox()
def delete_api(self):
selection = self.listbox.curselection()
if not selection:
messagebox.showwarning("警告", "请先选择一个API")
return
index = selection[0]
name = list(self.custom_apis.keys())[index]
if messagebox.askyesno("确认", f"确定要删除API '{name}' 吗?"):
del self.custom_apis[name]
self.update_listbox()
def save_and_close(self):
self.result = self.custom_apis
self.top.destroy()
def cancel(self):
self.top.destroy()
class ApiDetailDialog:
def __init__(self, parent, name, url, font):
self.top = tk.Toplevel(parent)
self.top.title("API详情" if name else "添加API")
self.top.geometry("400x200")
self.top.resizable(False, False)
self.top.transient(parent)
self.top.grab_set()
self.result = None
self.font = font
self.create_widgets(name, url)
def create_widgets(self, name, url):
main_frame = ttk.Frame(self.top, padding="15")
main_frame.pack(fill=tk.BOTH, expand=True)
ttk.Label(main_frame, text="API名称:", font=self.font).grid(row=0, column=0, sticky=tk.W, pady=10)
self.name_var = tk.StringVar(value=name)
name_entry = ttk.Entry(main_frame, textvariable=self.name_var, width=30, font=self.font)
name_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), pady=10, padx=10)
ttk.Label(main_frame, text="API URL:", font=self.font).grid(row=1, column=0, sticky=tk.W, pady=10)
self.url_var = tk.StringVar(value=url)
url_entry = ttk.Entry(main_frame, textvariable=self.url_var, width=30, font=self.font)
url_entry.grid(row=1, column=1, sticky=(tk.W, tk.E), pady=10, padx=10)
button_frame = ttk.Frame(main_frame)
button_frame.grid(row=2, column=0, columnspan=2, pady=20)
ttk.Button(button_frame, text="确定",
command=self.save, style="Success.TButton").pack(side=tk.RIGHT, padx=10, ipadx=10)
ttk.Button(button_frame, text="取消",
command=self.cancel, style="Primary.TButton").pack(side=tk.RIGHT, padx=10, ipadx=10)
main_frame.columnconfigure(1, weight=1)
def save(self):
name = self.name_var.get().strip()
url = self.url_var.get().strip()
if not name:
messagebox.showwarning("警告", "请输入API名称")
return
if not url:
messagebox.showwarning("警告", "请输入API URL")
return
self.result = (name, url)
self.top.destroy()
def cancel(self):
self.top.destroy()
def main():
root = tk.Tk()
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1)
except:
pass
app = WallpaperChanger(root)
root.mainloop()
if __name__ == "__main__":
main()
下载
[/color" target="_blank" rel="noopener noreferrer nofollow">https://wwkz.lanzoum.com/iOjQi39fncve
密码:eaeb
主要功能
控制
缓存系统
安装要求
系统要求
依赖库安装
在运行程序前,请先安装所需依赖:
pip install requests pillow pystray pywin32 winshell
使用指南
首次运行
[ol]
[/ol]
壁纸源选择
自动更换设置
缓存管理
系统集成
故障排除
常见问题
Q: 壁纸无法正常设置
A: 请检查程序是否以管理员权限运行,某些系统设置需要管理员权限。
Q: API无法访问
A: 程序会自动使用缓存中的图片,并提示用户。检查网络连接或尝试其他壁纸源。
Q: 预览图加载失败
A: 可能是网络问题或API暂时不可用,点击预览图区域可重新加载。
Q: 开机自启动不生效
A: 某些安全软件可能会阻止程序创建启动项,请检查安全软件设置。
缓存位置
wp-52pojie/
├── bing/ # 必应壁纸缓存
├── genshin/ # 原神图片缓存
├── nasa/ # NASA图片缓存
└── custom_xxx/ # 自定义API缓存
联系支持
如果您在使用过程中遇到问题或有改进建议,请联系我们:

