当前位置: 首页 > news >正文

Python数据可视化艺术:动态壁纸生成器

解决方案概述

我们将使用以下技术:

Pygame:用于创建图形和动画

Perlin噪声:生成自然的流动效果

Win32 API:将生成的动画设置为桌面壁纸

多线程:确保壁纸更新不影响主程序运行

完整代码实现

import pygame
import numpy as np
import random
import win32gui
import win32con
import win32api
import threading
import math
import sys
import os
from pygame.locals import *# 初始化pygame
pygame.init()# 获取屏幕尺寸
screen_info = pygame.display.Info()
SCREEN_WIDTH, SCREEN_HEIGHT = screen_info.current_w, screen_info.current_h# 创建隐藏窗口用于渲染
os.environ['SDL_VIDEO_WINDOW_POS'] = f"{SCREEN_WIDTH + 100},0"
screen = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))# Perlin噪声生成器
class PerlinNoiseGenerator:def __init__(self, seed=None):self.seed = seed if seed is not None else random.randint(0, 1000000)random.seed(self.seed)self.permutation = list(range(256))random.shuffle(self.permutation)self.permutation = self.permutation * 2def fade(self, t):return t * t * t * (t * (t * 6 - 15) + 10)def lerp(self, a, b, x):return a + x * (b - a)def grad(self, hash, x, y, z):h = hash & 15u = x if h < 8 else yv = y if h < 4 else (x if h in (12, 14) else z)return (u if (h & 1) == 0 else -u) + (v if (h & 2) == 0 else -v)def noise(self, x, y=0, z=0):X = int(x) & 255Y = int(y) & 255Z = int(z) & 255x -= math.floor(x)y -= math.floor(y)z -= math.floor(z)u = self.fade(x)v = self.fade(y)w = self.fade(z)A = self.permutation[X] + YAA = self.permutation[A] + ZAB = self.permutation[A + 1] + ZB = self.permutation[X + 1] + YBA = self.permutation[B] + ZBB = self.permutation[B + 1] + Zreturn self.lerp(self.lerp(self.lerp(self.grad(self.permutation[AA], x, y, z),self.grad(self.permutation[BA], x - 1, y, z),u),self.lerp(self.grad(self.permutation[AB], x, y - 1, z),self.grad(self.permutation[BB], x - 1, y - 1, z),u),v)# 粒子系统
class ParticleSystem:def __init__(self, num_particles=500):self.particles = []self.colors = [(255, 0, 100), (0, 200, 255), (100, 255, 0),(255, 150, 0), (180, 0, 255), (0, 150, 255)]self.generate_particles(num_particles)def generate_particles(self, num):for _ in range(num):x = random.randint(0, SCREEN_WIDTH)y = random.randint(0, SCREEN_HEIGHT)size = random.randint(2, 6)speed = random.uniform(0.5, 3.0)angle = random.uniform(0, 2 * math.pi)color = random.choice(self.colors)life = random.randint(100, 300)self.particles.append([x, y, size, speed, angle, color, life])def update(self, noise_gen, time):for p in self.particles:# 使用Perlin噪声影响运动方向noise_val = noise_gen.noise(p[0] * 0.01, p[1] * 0.01, time * 0.1)p[4] += noise_val * 0.2# 更新位置p[0] += math.cos(p[4]) * p[3]p[1] += math.sin(p[4]) * p[3]# 生命周期p[6] -= 1# 边界处理if p[0] < -50 or p[0] > SCREEN_WIDTH + 50 or p[1] < -50 or p[1] > SCREEN_HEIGHT + 50 or p[6] <= 0:p[0] = random.randint(0, SCREEN_WIDTH)p[1] = random.randint(0, SCREEN_HEIGHT)p[6] = random.randint(100, 300)def draw(self, surface):for p in self.particles:alpha = min(255, p[6] * 2)color = (p[5][0], p[5][1], p[5][2], alpha)pygame.draw.circle(surface, color, (int(p[0]), int(p[1])), p[2])# 动态几何形状
class DynamicShapes:def __init__(self):self.shapes = []self.generate_shapes()def generate_shapes(self):# 创建不同几何形状for _ in range(8):shape_type = random.choice(['circle', 'triangle', 'square', 'hexagon'])size = random.randint(80, 200)x = random.randint(size, SCREEN_WIDTH - size)y = random.randint(size, SCREEN_HEIGHT - size)color = (random.randint(50, 200),random.randint(50, 200),random.randint(50, 200),random.randint(30, 100))speed = random.uniform(0.5, 2.0)angle = random.uniform(0, 2 * math.pi)rotation_speed = random.uniform(-0.03, 0.03)self.shapes.append([shape_type, x, y, size, color, speed, angle, rotation_speed, 0])def update(self, time):for s in self.shapes:# 更新位置s[1] += math.cos(s[6]) * s[5]s[2] += math.sin(s[6]) * s[5]s[7] += s[7]  # 旋转s[8] = time  # 存储时间用于动画# 边界反弹if s[1] < s[3] or s[1] > SCREEN_WIDTH - s[3]:s[6] = math.pi - s[6]if s[2] < s[3] or s[2] > SCREEN_HEIGHT - s[3]:s[6] = -s[6]def draw(self, surface):for s in self.shapes:color = s[4]if s[0] == 'circle':pygame.draw.circle(surface, color, (int(s[1]), int(s[2])), s[3], 3)# 内部动画inner_size = s[3] * 0.7 + math.sin(s[8] * 0.05) * 10pygame.draw.circle(surface, color, (int(s[1]), int(s[2])), int(inner_size), 1)elif s[0] == 'triangle':points = []for i in range(3):angle = s[7] + i * (2 * math.pi / 3)px = s[1] + math.cos(angle) * s[3]py = s[2] + math.sin(angle) * s[3]points.append((px, py))pygame.draw.polygon(surface, color, points, 3)elif s[0] == 'square':rect = pygame.Rect(0, 0, s[3]*2, s[3]*2)rect.center = (s[1], s[2])pygame.draw.rect(surface, color, rect, 3, border_radius=10)elif s[0] == 'hexagon':points = []for i in range(6):angle = s[7] + i * (math.pi / 3)px = s[1] + math.cos(angle) * s[3]py = s[2] + math.sin(angle) * s[3]points.append((px, py))pygame.draw.polygon(surface, color, points, 3)# 设置壁纸的函数
def set_wallpaper(image_path):key = win32con.HKEY_CURRENT_USERsubkey = "Control Panel\\Desktop"try:reg_key = win32api.RegOpenKeyEx(key, subkey, 0, win32con.KEY_WRITE)win32api.RegSetValueEx(reg_key, "WallpaperStyle", 0, win32con.REG_SZ, "10")  # 填充win32api.RegSetValueEx(reg_key, "TileWallpaper", 0, win32con.REG_SZ, "0")win32api.RegCloseKey(reg_key)win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, image_path, win32con.SPIF_UPDATEINIFILE)return Trueexcept Exception as e:print(f"设置壁纸时出错: {e}")return False# 壁纸更新线程
class WallpaperUpdater(threading.Thread):def __init__(self, update_interval=5):super().__init__()self.update_interval = update_intervalself.running = Trueself.daemon = Truedef run(self):temp_file = os.path.join(os.getenv('TEMP'), 'python_wallpaper.bmp')while self.running:# 保存当前帧为临时文件pygame.image.save(screen, temp_file)# 设置壁纸set_wallpaper(temp_file)# 等待下一次更新pygame.time.wait(self.update_interval * 1000)def stop(self):self.running = False# 主函数
def main():global screen# 创建噪声生成器noise_gen = PerlinNoiseGenerator()# 创建粒子系统particle_system = ParticleSystem(800)# 创建动态形状dynamic_shapes = DynamicShapes()# 创建半透明表面用于轨迹效果overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)# 启动壁纸更新线程wallpaper_thread = WallpaperUpdater(update_interval=10)wallpaper_thread.start()# 创建控制窗口control_window = pygame.display.set_mode((300, 200))pygame.display.set_caption("动态壁纸控制器")# 字体font = pygame.font.SysFont(None, 24)# 主循环clock = pygame.time.Clock()time = 0running = Truewhile running:# 处理控制窗口事件for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseelif event.type == pygame.KEYDOWN:if event.key == pygame.K_ESCAPE:running = Falseelif event.key == pygame.K_r:# 重置粒子系统particle_system = ParticleSystem(800)elif event.key == pygame.K_s:# 重置动态形状dynamic_shapes = DynamicShapes()# 更新time += 0.05particle_system.update(noise_gen, time)dynamic_shapes.update(time)# 绘制# 添加淡出效果(创建运动轨迹)overlay.fill((0, 0, 0, 15), special_flags=pygame.BLEND_RGBA_MULT)screen.blit(overlay, (0, 0))# 绘制粒子particle_system.draw(screen)# 绘制动态形状dynamic_shapes.draw(screen)# 绘制控制窗口control_window.fill((40, 40, 60))# 显示控制信息texts = ["动态壁纸生成器","按 ESC 退出程序","按 R 重置粒子","按 S 重置形状",f"粒子数量: {len(particle_system.particles)}",f"形状数量: {len(dynamic_shapes.shapes)}"]for i, text in enumerate(texts):text_surface = font.render(text, True, (200, 220, 255))control_window.blit(text_surface, (20, 20 + i * 30))pygame.display.flip()clock.tick(30)# 清理wallpaper_thread.stop()wallpaper_thread.join(timeout=1.0)pygame.quit()sys.exit()if __name__ == "__main__":main()

运行说明

  1. 安装必要的库:

    bash
    pip install pygame numpy pywin32
    
  2. 运行程序后会出现控制窗口:

    按 ESC 退出程序按 R 重置粒子系统按 S 重置几何形状
    
  3. 程序会自动将生成的动画设置为桌面壁纸(每10秒更新一次)

技术亮点

  1. Perlin噪声:用于生成自然的粒子运动路径,避免机械感

  2. 粒子系统:800个彩色粒子在屏幕上流动,每个粒子有独立属性

  3. 动态几何:随机生成的几何图形在屏幕上移动、旋转和缩放

  4. 壁纸设置:使用Win32 API实时更新桌面壁纸

  5. 多线程:壁纸更新在后台线程进行,不影响主渲染循环

  6. 淡出效果:通过半透明覆盖层创建粒子轨迹效果

  7. 响应式设计:自动适应不同屏幕分辨率

自定义选项

  1. 你可以调整以下参数来改变壁纸效果:

  2. ParticleSystem 中的粒子数量

  3. DynamicShapes 中的形状数量和类型

  4. WallpaperUpdater 中的更新间隔

  5. 修改粒子颜色和形状颜色

  6. 调整粒子大小和速度范围

注意事项

  1. 该程序仅在Windows系统上测试通过
  2. 首次运行时可能需要允许程序更改系统设置
  3. 退出程序后,最后一次生成的壁纸会保留在桌面上
  4. 对于性能较弱的电脑,可以减少粒子数量或增大壁纸更新间隔
  5. 这个动态壁纸生成器展示了Python在创意编程和图形生成方面的强大能力,结合了数学算法、粒子系统和系统编程技术。
http://www.xdnf.cn/news/993025.html

相关文章:

  • 《C++初阶之类和对象》【类 + 类域 + 访问限定符 + 对象的大小 + this指针】
  • Vue3+TypeScript实现中介者模式
  • 【Docker管理工具】安装容器管理工具Oxker
  • 通信网络编程2.0——JAVA
  • HALCON第五讲-> 形状匹配
  • 每日八股文6.12
  • 蓝桥杯20112 不同的总分值
  • 网页怎么调用字体ttf文件?
  • Go 语言安装指南:并解决 `url.JoinPath` 及 `Exec format error` 问题
  • [论文阅读] 系统架构 | 零售 IT 中的微服务与实时处理:开源工具链与部署策略综述
  • MySQL数据库:关系型数据库的基石
  • AVL树的平衡艺术:用C++写出会“站立”的二叉树(未完待续)
  • 【SAS求解多元回归方程】REG多元回归分析-多元一次回归
  • windows基线配置
  • ss928v100模型的导出、量化和转换
  • 中科院1区|IF6.7:基于PCA/OPLS-DA和KEGG通路分析的多组学整合,揭示沙棘-水飞蓟复方改善高脂血症的分子基础
  • C语言:指针进阶(下)
  • OpenAI推出专业级大模型o3-pro:为高精度任务而生
  • 【技术追踪】纵向 MRI 生成和弥漫性胶质瘤生长预测的治疗感知扩散概率模型(TMI-2025)
  • 商标注册小类怎么选?业务+战略双维度匹配
  • 离线部署openstack 2024.1 nova
  • C++实现文本编辑功能
  • cocosCreator 2.4 使用 flavor 配置安卓多渠道
  • OpneLayers 创建地图卷帘
  • 系统设计基本功:流量与存储需求估算
  • 40 C 语言日期与时间函数详解:time、ctime、difftime、clock(含 UTC/本地时间转换)
  • PostGIS实现波段添加导入【ST_AddBand】
  • Linux相关问题整理
  • 如何利用智能助手提升工作效率:从入门到实践
  • C语言学习20250611