基于Python實(shí)現(xiàn)桌面動(dòng)態(tài)文字壁紙的詳細(xì)步驟
前言
2026年了,看著電腦桌面靜態(tài)的壁紙,想著是否能夠整點(diǎn)動(dòng)態(tài)效果上去,于是。
這個(gè)動(dòng)態(tài)壁紙應(yīng)用是一個(gè)基于Python的桌面應(yīng)用程序,采用了經(jīng)典的MVC(Model-View-Controller)架構(gòu)模式。應(yīng)用的核心設(shè)計(jì)思想是將靜態(tài)壁紙與動(dòng)態(tài)視覺效果相結(jié)合,創(chuàng)造出既美觀又不干擾用戶正常使用的桌面環(huán)境。
效果


實(shí)現(xiàn)過(guò)程
該程序能夠在桌面背景上顯示具有多種動(dòng)畫效果的"2026"文字,并支持實(shí)時(shí)配置。
一、技術(shù)架構(gòu)概覽
1.1 核心技術(shù)棧
- 界面框架: tkinter (GUI控制面板) - 系統(tǒng)交互: pywin32 (Windows API調(diào)用) - 圖像處理: Pillow (圖像生成與處理) - 動(dòng)畫引擎: 基于時(shí)間的數(shù)學(xué)函數(shù)計(jì)算
1.2 程序結(jié)構(gòu)
DynamicWallpaper2026類
├── 初始化模塊 (__init__)
├── UI界面模塊 (setup_ui)
├── 壁紙控制模塊
│ ├── start_dynamic_wallpaper
│ ├── stop_wallpaper
│ └── create_wallpaper_window
├── 動(dòng)畫渲染模塊
│ ├── animate (主循環(huán))
│ ├── draw_dynamic_text (文字效果)
│ └── draw_particles (粒子效果)
└── 工具函數(shù)模塊
├── change_color_palette
└── on_closing
二、詳細(xì)實(shí)現(xiàn)步驟分析
2.1 初始化階段
步驟1:環(huán)境檢測(cè)與權(quán)限驗(yàn)證
# 檢查管理員權(quán)限(Windows壁紙?jiān)O(shè)置需要管理員權(quán)限)
if not ctypes.windll.shell32.IsUserAnAdmin():
# 自動(dòng)提權(quán)重新運(yùn)行
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, ...)
步驟2:程序核心初始化
def __init__(self):
# 1. 創(chuàng)建主窗口
self.root = tk.Tk()
# 2. 獲取屏幕分辨率
self.screen_width = self.root.winfo_screenwidth()
self.screen_height = self.root.winfo_screenheight()
# 3. 初始化狀態(tài)變量
self.is_running = False # 運(yùn)行狀態(tài)標(biāo)志
self.wallpaper_hwnd = None # 壁紙窗口句柄
# 4. 配置動(dòng)畫效果參數(shù)
self.effects = {
'rotation': True, # 旋轉(zhuǎn)效果
'pulse': True, # 脈動(dòng)效果
'color_shift': True, # 顏色變換
'particles': True, # 粒子效果
'glow': True # 發(fā)光效果
}
# 5. 預(yù)定義配色方案
self.color_palettes = [...]
self.current_palette = 0
2.2 用戶界面構(gòu)建
步驟3:控制面板創(chuàng)建
def setup_ui(self):
# 1. 窗口樣式設(shè)置
self.root.configure(bg='#2C3E50') # 深色主題
# 2. 效果開關(guān)控件(使用Checkbutton)
for effect, enabled in self.effects.items():
var = tk.BooleanVar(value=enabled)
self.effect_vars[effect] = var
# 創(chuàng)建對(duì)應(yīng)的復(fù)選框控件
# 3. 控制按鈕組
# - 啟動(dòng)動(dòng)態(tài)壁紙按鈕
# - 更換配色方案按鈕
# - 停止壁紙按鈕
# 4. 狀態(tài)顯示區(qū)域
self.status_label = tk.Label(...)
# 5. 使用說(shuō)明文本
2.3 壁紙啟動(dòng)流程
步驟4:資源預(yù)加載
def start_dynamic_wallpaper(self):
# 1. 防重復(fù)啟動(dòng)檢查
if self.is_running: return
# 2. 更新效果配置
for effect, var in self.effect_vars.items():
self.effects[effect] = var.get()
# 3. 加載背景圖片
wallpaper_path = "C:\\...\\bing_wallpaper.jpg"
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
)
# 4. 預(yù)加載字體(性能優(yōu)化)
self.base_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 150)
# 5. 初始化動(dòng)畫計(jì)時(shí)器
self.animation_start_time = time.time()
self.last_update_time = 0
self.frame_count = 0
# 6. 啟動(dòng)動(dòng)畫循環(huán)
self.is_running = True
self.root.after(100, self.start_animation_loop)
2.4 動(dòng)畫循環(huán)機(jī)制
步驟5:動(dòng)畫主循環(huán)
def animate(self):
# 1. 狀態(tài)檢查
if not self.is_running: return
# 2. 幀率控制(15FPS限制)
current_time = time.time()
if current_time - self.last_update_time < 0.066: # ~15FPS
self.root.after(10, self.animate) # 延遲重試
return
# 3. 圖像合成管道
# 復(fù)制背景 -> 繪制文字 -> 繪制粒子 -> 保存圖片
# 4. 壁紙更新(性能優(yōu)化:選擇性更新)
update_wallpaper = False
if current_time - self.last_wallpaper_time > 0.3:
update_wallpaper = True
elif self.frame_count % 3 == 0:
update_wallpaper = True
if update_wallpaper:
# 保存為BMP格式(Windows壁紙要求)
composite_image.convert('RGB').save("temp_wallpaper.bmp", 'BMP')
# 調(diào)用Windows API設(shè)置壁紙
ctypes.windll.user32.SystemParametersInfoW(20, 0, temp_path, 0)
# 5. 安排下一幀
self.root.after(10, self.animate)
2.5 動(dòng)態(tài)效果實(shí)現(xiàn)
步驟6:文字動(dòng)畫算法
def draw_dynamic_text(self, draw, current_time):
# 1. 脈動(dòng)效果(正弦函數(shù)控制大?。?
pulse_factor = 1.0 + 0.1 * math.sin(current_time * 2)
# 2. 旋轉(zhuǎn)效果(緩慢擺動(dòng))
rotation = math.sin(current_time * 0.5) * 5
# 3. 顏色漸變(線性插值)
color_index = int((current_time * 0.5) % len(colors))
next_color_index = (color_index + 1) % len(colors)
t = (current_time * 0.5) % 1
# RGB插值計(jì)算
r = int(r1 + (r2 - r1) * t)
g = int(g1 + (g2 - g1) * t)
b = int(b1 + (b2 - b1) * t)
# 4. 發(fā)光效果(多層繪制)
glow_steps = min(glow_intensity // 5, 10)
for i in range(glow_steps, 0, -1):
alpha = int(255 * i / glow_steps) # 透明度遞減
draw.text((x, y), "2026", fill=(r, g, b, alpha), font=font_obj)
步驟7:粒子系統(tǒng)實(shí)現(xiàn)
def draw_particles(self, draw, current_time):
# 1. 自適應(yīng)粒子數(shù)量(根據(jù)性能動(dòng)態(tài)調(diào)整)
base_particles = 30
if avg_fps < 10: base_particles = 15
elif avg_fps < 15: base_particles = 20
# 2. 粒子運(yùn)動(dòng)軌跡計(jì)算
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)
# 極坐標(biāo)轉(zhuǎn)笛卡爾坐標(biāo)
x = center_x + radius * math.cos(angle)
y = center_y + radius * math.sin(angle)
# 3. 粒子尺寸和透明度變化
size = 2 + 1.5 * math.sin(current_time * 1.5 + i)
draw.ellipse([x-size, y-size, x+size, y+size], fill=(r,g,b,180))
2.6 性能優(yōu)化策略
優(yōu)化1:字體對(duì)象緩存
# 避免每次循環(huán)重新加載字體
if not hasattr(self, 'current_font_size') or abs(font_size - self.current_font_size) > 5:
self.current_font = ImageFont.truetype("msyh.ttc", font_size)
self.current_font_size = font_size
優(yōu)化2:文字位置預(yù)計(jì)算
# 只在首次計(jì)算文字位置并緩存
if not hasattr(self, 'text_position'):
bbox = draw.textbbox((0, 0), "2026", font=font_obj)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
self.text_position = (x, y, text_width, text_height)
優(yōu)化3:壁紙更新頻率控制
# 降低壁紙文件寫入頻率
if current_time - self.last_wallpaper_time > 0.3: # 每0.3秒更新一次
update_wallpaper = True
elif self.frame_count % 3 == 0: # 每3幀強(qiáng)制更新
update_wallpaper = True
2.7 系統(tǒng)交互實(shí)現(xiàn)
步驟8:Windows壁紙?jiān)O(shè)置
def create_wallpaper_window(self):
# 1. 注冊(cè)窗口類
wc = win32gui.WNDCLASS()
wc.lpszClassName = "2026WallpaperClass"
wc.hbrBackground = win32gui.GetStockObject(win32con.NULL_BRUSH)
# 2. 創(chuàng)建透明全屏窗口
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, screen_width, screen_height,
0, 0, 0, None
)
# 3. 設(shè)置透明屬性
win32gui.SetLayeredWindowAttributes(hwnd, 0, 0, win32con.LWA_COLORKEY)
步驟9:壁紙更新API調(diào)用
# 使用Windows系統(tǒng)API更新壁紙
ctypes.windll.user32.SystemParametersInfoW(
20, # SPI_SETDESKWALLPAPER
0, # 保留參數(shù)
temp_path, # 壁紙文件路徑
0 # 立即更新標(biāo)志
)
2.8 清理與退出
步驟10:資源釋放
def stop_wallpaper(self):
# 1. 停止動(dòng)畫循環(huán)
self.is_running = False
# 2. 刪除臨時(shí)文件
if os.path.exists("temp_wallpaper.bmp"):
os.remove("temp_wallpaper.bmp")
# 3. 清理內(nèi)存對(duì)象
if hasattr(self, 'wallpaper_image'):
delattr(self, 'wallpaper_image')
# 4. 顯示控制窗口
self.root.deiconify()
三、關(guān)鍵技術(shù)要點(diǎn)總結(jié)
3.1 核心算法
- 時(shí)間驅(qū)動(dòng)的動(dòng)畫系統(tǒng):所有動(dòng)畫效果基于
time.time()計(jì)算 - 三角函數(shù)動(dòng)畫:使用
sin()和cos()實(shí)現(xiàn)平滑的周期性動(dòng)畫 - 顏色插值算法:在顏色間實(shí)現(xiàn)平滑過(guò)渡效果
- 粒子系統(tǒng)算法:極坐標(biāo)計(jì)算粒子運(yùn)動(dòng)軌跡
3.2 性能優(yōu)化
- 幀率控制:通過(guò)時(shí)間間隔檢查實(shí)現(xiàn)FPS限制
- 資源緩存:字體、位置等計(jì)算結(jié)果緩存復(fù)用
- 選擇性更新:降低壁紙文件寫入頻率
- 動(dòng)態(tài)調(diào)整:根據(jù)性能動(dòng)態(tài)調(diào)整粒子數(shù)量
3.3 用戶體驗(yàn)
- 實(shí)時(shí)配置:所有效果可實(shí)時(shí)開啟/關(guān)閉
- 多配色方案:提供5種預(yù)設(shè)配色方案
- 狀態(tài)反饋:實(shí)時(shí)顯示運(yùn)行狀態(tài)和提示信息
- 錯(cuò)誤處理:完善的異常捕獲和用戶提示
完整代碼
啟動(dòng)前,可以先按鈕相關(guān)庫(kù),創(chuàng)建 requirements.txt 文件:
pywin32>=305 Pillow>=10.0.0
安裝依賴:
pip install -r requirements.txt
完整python代碼
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動(dòng)態(tài)壁紙")
self.root.geometry("600x400")
# 獲取屏幕尺寸
self.screen_width = self.root.winfo_screenwidth()
self.screen_height = self.root.winfo_screenheight()
# 壁紙句柄和狀態(tài)控制
self.wallpaper_hwnd = None
self.is_running = False
# 效果設(shè)置
self.effects = {
'rotation': True,
'pulse': True,
'color_shift': True,
'particles': True,
'glow': True
}
# 顏色預(yù)設(shè)
self.color_palettes = [
['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'], # 明亮
['#6C5B7B', '#C06C84', '#F67280', '#F8B195', '#355C7D'], # 漸變
['#2A363B', '#FF847C', '#E84A5F', '#FECEA8', '#99B898'], # 對(duì)比
['#00B4DB', '#0083B0', '#00B4DB', '#0083B0', '#00B4DB'], # 藍(lán)色系
['#FF9A9E', '#FAD0C4', '#FAD0C4', '#FF9A9E', '#A18CD1'], # 柔和
]
self.current_palette = 0
self.setup_ui()
def setup_ui(self):
# 設(shè)置窗口樣式
self.root.configure(bg='#2C3E50')
# 標(biāo)題
title = tk.Label(
self.root,
text="2026動(dòng)態(tài)文字壁紙",
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")
# 效果開關(guān)
effects_frame = tk.LabelFrame(
control_frame,
text="效果設(shè)置",
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': '旋轉(zhuǎn)動(dòng)畫',
'pulse': '脈動(dòng)效果',
'color_shift': '顏色變換',
'particles': '粒子效果',
'glow': '發(fā)光效果'
}[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="啟動(dòng)動(dòng)態(tài)壁紙",
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)
# 狀態(tài)顯示
self.status_label = tk.Label(
self.root,
text="就緒",
font=("微軟雅黑", 10),
fg="#95A5A6",
bg="#2C3E50"
)
self.status_label.pack(pady=10)
# 說(shuō)明文字
info_text = """動(dòng)態(tài)效果說(shuō)明:
? 旋轉(zhuǎn)動(dòng)畫:2026文字會(huì)緩慢旋轉(zhuǎn)
? 脈動(dòng)效果:文字會(huì)有節(jié)奏地放大縮小
? 顏色變換:文字顏色會(huì)逐漸變化
? 粒子效果:周圍有飄動(dòng)的粒子動(dòng)畫
? 發(fā)光效果:文字有發(fā)光效果
提示:?jiǎn)?dòng)壁紙后,可以最小化此窗口,壁紙會(huì)繼續(xù)運(yùn)行。"""
info = tk.Label(
self.root,
text=info_text,
font=("微軟雅黑", 9),
fg="#BDC3C7",
bg="#2C3E50",
justify="left"
)
info.pack(pady=10, padx=20)
# 綁定關(guān)閉事件
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
def start_dynamic_wallpaper(self):
"""啟動(dòng)動(dòng)態(tài)壁紙"""
# 防止重復(fù)啟動(dòng)
if self.is_running:
self.status_label.config(text="動(dòng)態(tài)壁紙已在運(yùn)行", fg="#F39C12")
return
# 更新效果設(shè)置
for effect, var in self.effect_vars.items():
self.effects[effect] = var.get()
# 預(yù)加載和初始化
self.status_label.config(text="正在初始化...", fg="#F39C12")
self.root.update() # 強(qiáng)制更新UI顯示狀態(tài)
# 加載壁紙圖片
wallpaper_path = r"C:\Users\Administrator\Pictures\bing_wallpapers\bing_wallpaper_20251224_130106.jpg"
try:
self.wallpaper_image = Image.open(wallpaper_path).convert('RGBA')
# 調(diào)整壁紙尺寸到屏幕大小
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
# 預(yù)加載字體(避免每次循環(huán)重新加載)
try:
self.base_font = ImageFont.truetype("C:\\Windows\\Fonts\\msyh.ttc", 150)
except:
self.base_font = ImageFont.load_default()
# 初始化動(dòng)畫狀態(tài)
self.animation_start_time = time.time()
self.last_update_time = 0
self.frame_count = 0
# 設(shè)置運(yùn)行狀態(tài)
self.is_running = True
# 延遲啟動(dòng)動(dòng)畫循環(huán),讓UI有時(shí)間響應(yīng)
self.root.after(100, self.start_animation_loop)
self.status_label.config(text="動(dòng)態(tài)壁紙已啟動(dòng)", fg="#2ECC71")
def start_animation_loop(self):
"""啟動(dòng)動(dòng)畫循環(huán)"""
if self.is_running:
self.animate()
def create_wallpaper_window(self):
"""創(chuàng)建壁紙窗口"""
if self.wallpaper_hwnd:
win32gui.DestroyWindow(self.wallpaper_hwnd)
# 注冊(cè)窗口類
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)
# 創(chuàng)建全屏窗口
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
)
# 設(shè)置窗口為分層透明窗口
win32gui.SetLayeredWindowAttributes(hwnd, 0, 0, win32con.LWA_COLORKEY)
# 顯示窗口
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
self.wallpaper_hwnd = hwnd
self.root.withdraw() # 隱藏控制窗口
def animate(self):
"""執(zhí)行動(dòng)畫循環(huán)"""
# 檢查是否仍在運(yùn)行
if not self.is_running or not hasattr(self, 'wallpaper_image'):
return
try:
# 獲取當(dāng)前時(shí)間
current_time = time.time()
# 性能優(yōu)化:限制更新頻率(最多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
# 復(fù)制壁紙圖像作為基礎(chǔ)
composite_image = self.wallpaper_image.copy()
draw = ImageDraw.Draw(composite_image)
# 繪制動(dòng)態(tài)文字
self.draw_dynamic_text(draw, current_time)
# 如果有粒子效果,繪制粒子(優(yōu)化粒子數(shù)量)
if self.effects['particles']:
self.draw_particles(draw, current_time)
# 保存臨時(shí)壁紙文件
temp_wallpaper_path = os.path.join(os.path.dirname(__file__), "temp_wallpaper.bmp")
# 性能優(yōu)化:只在需要時(shí)更新壁紙
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幀強(qiáng)制更新一次
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"設(shè)置壁紙時(shí)出錯(cuò): {e}")
# 安排下一次更新(使用更短的延遲,但通過(guò)時(shí)間檢查控制頻率)
self.root.after(10, self.animate)
def draw_dynamic_text(self, draw, current_time):
"""繪制動(dòng)態(tài)文字"""
colors = self.color_palettes[self.current_palette]
# 計(jì)算動(dòng)態(tài)效果(優(yōu)化計(jì)算頻率)
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))
# 計(jì)算顏色變化
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)
# 使用預(yù)加載的字體
base_font_size = 150
base_font_obj = self.base_font
# 使用基礎(chǔ)字體計(jì)算固定位置
text = "2026"
# 使用draw.textbbox計(jì)算文字邊界框(優(yōu)化:緩存計(jì)算結(jié)果)
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
# 創(chuàng)建實(shí)際使用的字體(帶脈沖效果)
font_size = int(base_font_size * pulse_factor)
# 性能優(yōu)化:字體大小變化不大時(shí)重用字體對(duì)象
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
# 如果有發(fā)光效果,繪制發(fā)光(優(yōu)化:減少發(fā)光層數(shù))
if self.effects['glow']:
glow_steps = min(glow_intensity // 5, 10) # 限制最大層數(shù)
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)
# 如果有旋轉(zhuǎn)效果,繪制第二個(gè)旋轉(zhuǎn)的文字(簡(jiǎn)化效果)
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]
# 性能優(yōu)化:減少粒子數(shù)量,根據(jù)幀數(shù)動(dòng)態(tài)調(diào)整
base_particles = 30
# 如果幀率較低,進(jìn)一步減少粒子數(shù)量
if hasattr(self, 'last_update_time') and hasattr(self, 'frame_count'):
if self.frame_count > 10:
# 計(jì)算平均幀率
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):
# 優(yōu)化計(jì)算:使用預(yù)計(jì)算的參數(shù)
angle = current_time * 0.3 + i * (2 * math.pi / num_particles) # 降低旋轉(zhuǎn)速度
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)
# 粒子大小和顏色(簡(jiǎn)化計(jì)算)
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)
# 繪制粒子(簡(jiǎn)化透明度)
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):
"""停止壁紙"""
# 設(shè)置停止?fàn)顟B(tài)
self.is_running = False
# 清理臨時(shí)文件
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
# 清理相關(guān)屬性
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="動(dòng)態(tài)壁紙已停止", fg="#E74C3C")
self.root.deiconify() # 顯示控制窗口
self.status_label.config(text="壁紙已停止", fg="#E74C3C")
def on_closing(self):
"""關(guān)閉程序"""
self.stop_wallpaper()
self.root.quit()
self.root.destroy()
def main():
"""主函數(shù)"""
try:
# 檢查是否以管理員身份運(yùn)行
if not ctypes.windll.shell32.IsUserAnAdmin():
# 如果不是管理員,嘗試重新以管理員身份運(yùn)行
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("錯(cuò)誤", f"程序運(yùn)行時(shí)發(fā)生錯(cuò)誤:{str(e)}")
if __name__ == "__main__":
main()
以上就是基于Python實(shí)現(xiàn)桌面動(dòng)態(tài)文字壁紙的詳細(xì)步驟的詳細(xì)內(nèi)容,更多關(guān)于Python桌面動(dòng)態(tài)文字壁紙的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python+OpenCV實(shí)現(xiàn)黑白老照片上色功能
我們都知道,有很多經(jīng)典的老照片,受限于那個(gè)時(shí)代的技術(shù),只能以黑白的形式傳世。盡管黑白照片別有一番風(fēng)味,但是彩色照片有時(shí)候能給人更強(qiáng)的代入感。本文就來(lái)用Python和OpenCV實(shí)現(xiàn)老照片上色功能,需要的可以參考一下2023-02-02
python爬蟲入門教程--利用requests構(gòu)建知乎API(三)
這篇文章主要給大家介紹了關(guān)于python爬蟲入門之利用requests構(gòu)建知乎API的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05
Python實(shí)現(xiàn)Socket通信建立TCP反向連接
本文將記錄學(xué)習(xí)基于 Socket 通信機(jī)制建立 TCP 反向連接,借助 Python 腳本實(shí)現(xiàn)主機(jī)遠(yuǎn)程控制的目的。感興趣的可以了解一下2021-08-08
django之用戶、用戶組及權(quán)限設(shè)置方式
這篇文章主要介紹了django之用戶、用戶組及權(quán)限設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
5個(gè)很好的Python面試題問(wèn)題答案及分析
這篇文章主要介紹了5個(gè)很好的Python面試題問(wèn)題答案及分析,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
python中JWT用戶認(rèn)證的實(shí)現(xiàn)
這篇文章主要介紹了python中JWT用戶認(rèn)證的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
國(guó)產(chǎn)化設(shè)備鯤鵬CentOS7上源碼安裝Python3.7的過(guò)程詳解
這篇文章主要介紹了國(guó)產(chǎn)化設(shè)備鯤鵬CentOS7上源碼安裝Python3.7,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
盤點(diǎn)十個(gè)超級(jí)好用的高級(jí)Python腳本
這篇文章主要介紹了盤點(diǎn)十個(gè)超級(jí)好用的高級(jí)Python腳本,我們經(jīng)常會(huì)遇到一些大小問(wèn)題,其中有很多的問(wèn)題,都是可以使用一些簡(jiǎn)單的Python代碼就能解決,需要的朋友可以參考下2023-04-04

