|
import tkinter as tk
from tkinter import messagebox, font
import win32api
import win32con
import win32gui
import sys
import os
import time
import math
from threading import Thread
from PIL import Image, ImageDraw, ImageFont, ImageTk
import ctypes
import random
class DynamicWallpaper2026:
def __init__(self):
self.root = tk.Tk()
self.root.title("2026动态壁纸")
self.root.geometry("600x400")
# 获取屏幕尺寸
self.screen_width = self.root.winfo_screenwidth()
self.screen_height = self.root.winfo_screenheight()
# 壁纸句柄和状态控制
self.wallpaper_hwnd = None
self.is_running = False
# 效果设置
self.effects = {
'rotation': True,
'pulse': True,
'color_shift': True,
'particles': True,
'glow': True
}
# 颜色预设
self.color_palettes = [
['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'], # 明亮
['#6C5B7B', '#C06C84', '#F67280', '#F8B195', '#355C7D'], # 渐变
['#2A363B', '#FF847C', '#E84A5F', '#FECEA8', '#99B898'], # 对比
['#00B4DB', '#0083B0', '#00B4DB', '#0083B0', '#00B4DB'], # 蓝色系
['#FF9A9E', '#FAD0C4', '#FAD0C4', '#FF9A9E', '#A18CD1'], # 柔和
]
self.current_palette = 0
self.setup_ui()
def setup_ui(self):
# 设置窗口样式
self.root.configure(bg='#2C3E50')
# 标题
title = tk.Label(
self.root,
text="2026动态文字壁纸",
font=("微软雅黑", 24, "bold"),
fg="#ECF0F1",
bg="#2C3E50"
)
title.pack(pady=20)
# 效果控制面板
control_frame = tk.Frame(self.root, bg="#34495E")
control_frame.pack(pady=10, padx=20, fill="x")
# 效果开关
effects_frame = tk.LabelFrame(
control_frame,
text="效果设置",
font=("微软雅黑", 10),
fg="#BDC3C7",
bg="#34495E"
)
effects_frame.pack(fill="x", pady=5)
self.effect_vars = {}
row = 0
col = 0
for effect, enabled in self.effects.items():
var = tk.BooleanVar(value=enabled)
self.effect_vars[effect] = var
effect_name = {
'rotation': '旋转动画',
'pulse': '脉动效果',
'color_shift': '颜色变换',
'particles': '粒子效果',
'glow': '发光效果'
}[effect]
cb = tk.Checkbutton(
effects_frame,
text=effect_name,
variable=var,
font=("微软雅黑", 9),
fg="#ECF0F1",
bg="#34495E",
selectcolor="#2C3E50",
activebackground="#34495E",
activeforeground="#ECF0F1"
)
cb.grid(row=row, column=col, padx=10, pady=5, sticky="w")
col += 1
if col > 2:
col = 0
row += 1
# 控制按钮
button_frame = tk.Frame(self.root, bg="#2C3E50")
button_frame.pack(pady=20)
tk.Button(
button_frame,
text="启动动态壁纸",
command=self.start_dynamic_wallpaper,
font=("微软雅黑", 11, "bold"),
bg="#27AE60",
fg="white",
padx=20,
pady=10,
relief="flat",
cursor="hand2"
).pack(side="left", padx=10)
tk.Button(
button_frame,
text="更换配色方案",
command=self.change_color_palette,
font=("微软雅黑", 11),
bg="#3498DB",
fg="white",
padx=20,
pady=10,
relief="flat",
cursor="hand2"
).pack(side="left", padx=10)
tk.Button(
button_frame,
text="停止壁纸",
command=self.stop_wallpaper,
font=("微软雅黑", 11),
bg="#E74C3C",
fg="white",
padx=20,
pady=10,
relief="flat",
cursor="hand2"
).pack(side="left", padx=10)
# 状态显示
self.status_label = tk.Label(
self.root,
text="就绪",
font=("微软雅黑", 10),
fg="#95A5A6",
bg="#2C3E50"
)
self.status_label.pack(pady=10)
# 说明文字
info_text = """动态效果说明:
• 旋转动画:2026文字会缓慢旋转
• 脉动效果:文字会有节奏地放大缩小
• 颜色变换:文字颜色会逐渐变化
• 粒子效果:周围有飘动的粒子动画
• 发光效果:文字有发光效果
提示:启动壁纸后,可以最小化此窗口,壁纸会继续运行。"""
info = tk.Label(
self.root,
text=info_text,
font=("微软雅黑", 9),
fg="#BDC3C7",
bg="#2C3E50",
justify="left"
)
info.pack(pady=10, padx=20)
# 绑定关闭事件
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
def start_dynamic_wallpaper(self):
"""启动动态壁纸"""
# 防止重复启动
if self.is_running:
self.status_label.config(text="动态壁纸已在运行", fg="#F39C12")
return
# 更新效果设置
for effect, var in self.effect_vars.items():
self.effects[effect] = var.get()
# 预加载和初始化
self.status_label.config(text="正在初始化...", fg="#F39C12")
self.root.update() # 强制更新UI显示状态
# 加载壁纸图片
wallpaper_path = r"C:\Users\Administrator\Pictures\bing_wallpapers\bing_wallpaper_20251224_130106.jpg"
try:
self.wallpaper_image = Image.open(wallpaper_path).convert('RGBA')
# 调整壁纸尺寸到屏幕大小
self.wallpaper_image = self.wallpaper_image.resize((self.screen_width, self.screen_height), Image.Resampling.LANCZOS)
except Exception as e:
self.status_label.config(text=f"加载壁纸失败: {str(e)}", fg="#E74C3C")
return
# 预加载字体(避免每次循环重新加载)
try:
self.base_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 150)
except:
self.base_font = ImageFont.load_default()
# 初始化动画状态
self.animation_start_time = time.time()
self.last_update_time = 0
self.frame_count = 0
# 设置运行状态
self.is_running = True
# 延迟启动动画循环,让UI有时间响应
self.root.after(100, self.start_animation_loop)
self.status_label.config(text="动态壁纸已启动", fg="#2ECC71")
def start_animation_loop(self):
"""启动动画循环"""
if self.is_running:
self.animate()
def create_wallpaper_window(self):
"""创建壁纸窗口"""
if self.wallpaper_hwnd:
win32gui.DestroyWindow(self.wallpaper_hwnd)
# 注册窗口类
wc = win32gui.WNDCLASS()
wc.lpszClassName = "2026WallpaperClass"
wc.hbrBackground = win32gui.GetStockObject(win32con.NULL_BRUSH) # 透明背景
wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW
wc.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
class_atom = win32gui.RegisterClass(wc)
# 创建全屏窗口
hwnd = win32gui.CreateWindowEx(
win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT | win32con.WS_EX_TOPMOST,
class_atom,
"2026 Dynamic Wallpaper",
win32con.WS_POPUP,
0, 0, self.screen_width, self.screen_height,
0, 0, 0, None
)
# 设置窗口为分层透明窗口
win32gui.SetLayeredWindowAttributes(hwnd, 0, 0, win32con.LWA_COLORKEY)
# 显示窗口
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
self.wallpaper_hwnd = hwnd
self.root.withdraw() # 隐藏控制窗口
def animate(self):
"""执行动画循环"""
# 检查是否仍在运行
if not self.is_running or not hasattr(self, 'wallpaper_image'):
return
try:
# 获取当前时间
current_time = time.time()
# 性能优化:限制更新频率(最多15FPS)
if hasattr(self, 'last_update_time') and current_time - self.last_update_time < 0.066: # ~15FPS
self.root.after(10, self.animate)
return
self.last_update_time = current_time
self.frame_count += 1
# 复制壁纸图像作为基础
composite_image = self.wallpaper_image.copy()
draw = ImageDraw.Draw(composite_image)
# 绘制动态文字
self.draw_dynamic_text(draw, current_time)
# 如果有粒子效果,绘制粒子(优化粒子数量)
if self.effects['particles']:
self.draw_particles(draw, current_time)
# 保存临时壁纸文件
temp_wallpaper_path = os.path.join(os.path.dirname(__file__), "temp_wallpaper.bmp")
# 性能优化:只在需要时更新壁纸
update_wallpaper = False
if not hasattr(self, 'last_wallpaper_time'):
update_wallpaper = True
elif current_time - self.last_wallpaper_time > 0.3: # 降低壁纸更新频率
update_wallpaper = True
elif self.frame_count % 3 == 0: # 每3帧强制更新一次
update_wallpaper = True
if update_wallpaper:
composite_image.convert('RGB').save(temp_wallpaper_path, 'BMP')
import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, temp_wallpaper_path, 0)
self.last_wallpaper_time = current_time
except Exception as e:
print(f"设置壁纸时出错: {e}")
# 安排下一次更新(使用更短的延迟,但通过时间检查控制频率)
self.root.after(10, self.animate)
def draw_dynamic_text(self, draw, current_time):
"""绘制动态文字"""
colors = self.color_palettes[self.current_palette]
# 计算动态效果(优化计算频率)
pulse_factor = 1.0
rotation = 0
glow_intensity = 0
if self.effects['pulse']:
pulse_factor = 1.0 + 0.1 * math.sin(current_time * 2)
if self.effects['rotation']:
rotation = math.sin(current_time * 0.5) * 5
if self.effects['glow']:
glow_intensity = 50 + int(30 * math.sin(current_time * 3))
# 计算颜色变化
color_index = int((current_time * 0.5) % len(colors))
next_color_index = (color_index + 1) % len(colors)
t = (current_time * 0.5) % 1
from_color = colors[color_index]
to_color = colors[next_color_index]
# 插值颜色
r1, g1, b1 = int(from_color[1:3], 16), int(from_color[3:5], 16), int(from_color[5:7], 16)
r2, g2, b2 = int(to_color[1:3], 16), int(to_color[3:5], 16), int(to_color[5:7], 16)
r = int(r1 + (r2 - r1) * t)
g = int(g1 + (g2 - g1) * t)
b = int(b1 + (b2 - b1) * t)
text_color = (r, g, b, 255)
# 使用预加载的字体
base_font_size = 150
base_font_obj = self.base_font
# 使用基础字体计算固定位置
text = "2026"
# 使用draw.textbbox计算文字边界框(优化:缓存计算结果)
if not hasattr(self, 'text_position'):
temp_image = Image.new('RGBA', (1, 1), (0, 0, 0, 0))
temp_draw = ImageDraw.Draw(temp_image)
bbox = temp_draw.textbbox((0, 0), text, font=base_font_obj)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
x = (self.screen_width - text_width) // 2
y = (self.screen_height - text_height) // 2
self.text_position = (x, y, text_width, text_height)
else:
x, y, text_width, text_height = self.text_position
# 创建实际使用的字体(带脉冲效果)
font_size = int(base_font_size * pulse_factor)
# 性能优化:字体大小变化不大时重用字体对象
if not hasattr(self, 'current_font_size') or abs(font_size - self.current_font_size) > 5:
try:
font_obj = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", font_size)
self.current_font_size = font_size
self.current_font = font_obj
except:
font_obj = ImageFont.load_default()
else:
font_obj = self.current_font
# 如果有发光效果,绘制发光(优化:减少发光层数)
if self.effects['glow']:
glow_steps = min(glow_intensity // 5, 10) # 限制最大层数
for i in range(glow_steps, 0, -1):
alpha = int(255 * i / glow_steps)
glow_color = (r, g, b, alpha)
draw.text((x, y), text, fill=glow_color, font=font_obj)
# 绘制主文字
draw.text((x, y), text, fill=text_color, font=font_obj)
# 如果有旋转效果,绘制第二个旋转的文字(简化效果)
if self.effects['rotation']:
rotated_color = (r, g, b, 80)
draw.text((x, y), text, fill=rotated_color, font=font_obj)
def draw_particles(self, draw, current_time):
"""绘制粒子效果"""
colors = self.color_palettes[self.current_palette]
# 性能优化:减少粒子数量,根据帧数动态调整
base_particles = 30
# 如果帧率较低,进一步减少粒子数量
if hasattr(self, 'last_update_time') and hasattr(self, 'frame_count'):
if self.frame_count > 10:
# 计算平均帧率
avg_fps = self.frame_count / (current_time - self.animation_start_time)
if avg_fps < 10:
base_particles = 15
elif avg_fps < 15:
base_particles = 20
# 生成粒子位置
num_particles = base_particles
for i in range(num_particles):
# 优化计算:使用预计算的参数
angle = current_time * 0.3 + i * (2 * math.pi / num_particles) # 降低旋转速度
radius = 250 + 30 * math.sin(current_time * 0.8 + i) # 减小半径变化幅度
x = self.screen_width // 2 + radius * math.cos(angle)
y = self.screen_height // 2 + radius * math.sin(angle)
# 粒子大小和颜色(简化计算)
size = 2 + 1.5 * math.sin(current_time * 1.5 + i) # 减小大小变化
color = colors[i % len(colors)]
r, g, b = int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)
# 绘制粒子(简化透明度)
draw.ellipse(
[x - size, y - size, x + size, y + size],
fill=(r, g, b, 180) # 固定透明度
)
def change_color_palette(self):
"""更换配色方案"""
self.current_palette = (self.current_palette + 1) % len(self.color_palettes)
colors = self.color_palettes[self.current_palette]
self.status_label.config(
text=f"已切换到配色方案 {self.current_palette + 1}",
fg="#3498DB"
)
def stop_wallpaper(self):
"""停止壁纸"""
# 设置停止状态
self.is_running = False
# 清理临时文件
try:
temp_wallpaper_path = os.path.join(os.path.dirname(__file__), "temp_wallpaper.bmp")
if os.path.exists(temp_wallpaper_path):
os.remove(temp_wallpaper_path)
except:
pass
# 清理相关属性
if hasattr(self, 'wallpaper_image'):
delattr(self, 'wallpaper_image')
if hasattr(self, 'wallpaper_hwnd'):
self.wallpaper_hwnd = None
if hasattr(self, 'last_wallpaper_time'):
delattr(self, 'last_wallpaper_time')
self.status_label.config(text="动态壁纸已停止", fg="#E74C3C")
self.root.deiconify() # 显示控制窗口
self.status_label.config(text="壁纸已停止", fg="#E74C3C")
def on_closing(self):
"""关闭程序"""
self.stop_wallpaper()
self.root.quit()
self.root.destroy()
def main():
"""主函数"""
try:
# 检查是否以管理员身份运行
if not ctypes.windll.shell32.IsUserAnAdmin():
# 如果不是管理员,尝试重新以管理员身份运行
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv), None, 1
)
sys.exit()
app = DynamicWallpaper2026()
app.root.mainloop()
except Exception as e:
messagebox.showerror("错误", f"程序运行时发生错误:{str(e)}")
if __name__ == "__main__":
main()
|
所有评论(0)