花哨桌面 经过几个版本的迭代 这个版本将是最后的版本,修复了之前群友们提出的一些问题.同时增加了一些优化
1.新增了托盘功能
退出
切换主题
启动开机启动
启动背景替换
设置图片大小
2.完善了更多主题,可选择,总有一款你喜欢的吧.........
灌篮高手
海贼王
火影忍者
马里奥
哪吒
七龙珠
犬夜叉
默认(宫崎骏风格)
3.摸鱼背景小游戏分数统计
4.自定义主题,大家可以根据自己喜好,在程序下面创建自己的资源,按照格式增加自己的主题风格,自己拓展
5.目前是win10系统开发的 win不兼容,会一点点编程的用源码自己编译改造下哦,随后源码奉上
6.程序也就是学习中突发灵感随手做的项目,大家勿喷哦,就是个娱乐的小玩意
7.软件也就不更新了,搞别的玩去了
下载链接
通过网盘分享的文件:花哨桌面(最终版本).rar
链接: https://pan.baidu.com/s/1YnVzRQE9YOAUoT5bg8VpoA?pwd=tnrj 提取码: tnrj
主题:

源码:
-
import ctypes
-
import os
-
import random
-
import sys
-
import time
-
import configparser
-
-
import winshell
-
from PyQt5.QtCore import Qt, QTimer, QPoint
-
from PyQt5.QtGui import QPainter, QColor, QPixmap, QCursor, QFont, QIcon
-
from PyQt5.QtWidgets import QApplication, QWidget, QSystemTrayIcon, QMenu, QAction, QInputDialog, QMessageBox
-
from PyQt5.QtGui import QMovie
-
from PyQt5.QtWidgets import QLabel
-
-
influence_range = 30 # 鼠标影响范围
-
QPixmap_size = 150 # 图标大小范围
-
-
-
# 开机自动启动实现
-
def add_to_startup():
-
"""通过创建启动项实现开机自动启动"""
-
try:
-
import winshell
-
from win32com.client import Dispatch
-
except ImportError:
-
print("请安装依赖库:pip install pywin32 winshell")
-
return
-
-
startup_folder = winshell.startup() # 获取启动目录
-
print("添加到启动项:", startup_folder)
-
shortcut_path = os.path.join(startup_folder, "花哨桌面.lnk")
-
if not os.path.exists(shortcut_path):
-
shell = Dispatch('WScript.Shell')
-
shortcut = shell.CreateShortCut(shortcut_path)
-
# 判断是否是打包后的exe环境
-
if getattr(sys, 'frozen', False):
-
# 打包后的exe路径
-
executable_path = sys.executable
-
else:
-
# 开发环境,使用当前脚本路径
-
executable_path = os.path.abspath(__file__)
-
# 快捷方式直接指向 .exe 文件,无需额外参数
-
shortcut.Targetpath = executable_path
-
shortcut.Arguments = '' # 因为目标已经是exe,不需要参数
-
shortcut.WorkingDirectory = os.path.dirname(executable_path) # 设置工作目录为exe所在目录
-
shortcut.save()
-
print("已添加到开机启动项")
-
else:
-
print("已存在开机启动项")
-
-
-
# 获取桌面窗口句柄并嵌入
-
def get_desktop_window():
-
# 查找ProgMan窗口
-
progman = ctypes.windll.user32.FindWindowW('ProgMan', None)
-
# 发送0x052C消息生成WorkerW窗口
-
ctypes.windll.user32.SendMessageW(progman, 0x052C, 0, 0)
-
hwnd = ctypes.windll.user32.FindWindowExW(None, None, 'WorkerW', None)
-
while hwnd:
-
# 查找包含SHELLDLL_DefView的子窗口
-
shell_view = ctypes.windll.user32.FindWindowExW(hwnd, None, 'SHELLDLL_DefView', None)
-
if shell_view:
-
return hwnd
-
hwnd = ctypes.windll.user32.FindWindowExW(None, hwnd, 'WorkerW', None)
-
return None
-
-
-
def get_resource_path(relative_path):
-
"""获取资源文件的路径,支持开发环境和打包后的 exe 环境"""
-
base_path = os.path.abspath(".")
-
# 判断是否是打包后的exe环境
-
if getattr(sys, 'frozen', False):
-
# 打包后的exe路径
-
base_path = sys.executable
-
else:
-
# 开发环境,使用当前脚本路径
-
base_path = os.path.abspath(__file__)
-
return os.path.join(os.path.dirname(base_path) , relative_path)
-
-
-
def get_base_path():
-
"""获取资源文件的基础路径"""
-
return get_resource_path("")
-
-
-
class Snowflake:
-
def __init__(self, max_width, max_height, image_paths):
-
self.x = random.randint(0, max_width)
-
self.y = random.randint(-max_height, 0) # 从屏幕上方随机位置生成
-
self.vx = random.uniform(-1, 1)
-
self.vy = random.uniform(0.5, 1.5) # 向下飘落的速度
-
self.radius = random.randint(5, 10)
-
self.color = QColor(255, 255, 255, 200)
-
# 随机加载素材目录下的图片
-
image_path = random.choice(image_paths)
-
self.image_name = os.path.basename(image_path) # 获取图片名称
-
self.pixmap = QPixmap(image_path)
-
self.pixmap = self.pixmap.scaled(self.radius * 3, self.radius * 3, Qt.KeepAspectRatio, Qt.SmoothTransformation)
-
-
def move(self, max_width, max_height, mouse_pos=None, speed_increment=0):
-
# 如果有鼠标位置信息,检测是否需要弹开
-
if mouse_pos:
-
mouse_x, mouse_y = mouse_pos
-
distance = ((self.x - mouse_x) ** 2 + (self.y - mouse_y) ** 2) ** 0.5
-
if distance < influence_range: # 增大鼠标影响范围阈值
-
self.vx = (self.x - mouse_x) * 0.2 # 增强弹开力度
-
self.vy = -(self.y - mouse_y) * 0.2 # 增强弹开力度
-
self.x += self.vx * 3 # 增强弹开力度
-
self.y += self.vy * 3 # 增强弹开力度
-
else:
-
self.x += self.vx
-
self.y += self.vy + speed_increment # 动态调整速度
-
else:
-
self.x += self.vx
-
self.y += self.vy + speed_increment # 动态调整速度
-
-
# 判断是否到达地面或逃出边界
-
if self.y >= max_height or self.x < 0 or self.x > max_width:
-
return False # 需要销毁
-
return True # 继续存在
-
-
def draw(self, painter):
-
# 使用图片绘制
-
# 将 self.x 和 self.y 转换为整数类型
-
painter.drawPixmap(QPoint(int(self.x - self.radius), int(self.y - self.radius)), self.pixmap)
-
-
-
class DynamicWallpaper(QWidget):
-
def __init__(self):
-
super().__init__()
-
self.base_path = get_base_path() # 获取基础路径
-
self.config_path = get_resource_path("花哨.ini")
-
self.config = configparser.ConfigParser()
-
self.config.read(self.config_path)
-
-
# 初始化主题相关变量
-
self.current_theme = self.config.get("Settings", "Theme", fallback="默认主题")
-
self.themes = self.load_themes()
-
self.load_theme(self.current_theme)
-
-
# 初始化开机启动状态
-
self.startup_enabled = self.config.getboolean("Settings", "Startup", fallback=False)
-
-
# 新增:初始化桌面背景修改状态
-
self.modify_background_enabled = self.config.getboolean("Settings", "ModifyBackground", fallback=True)
-
-
# 初始化系统托盘
-
self.tray_icon = QSystemTrayIcon(self)
-
self.init_tray_icon()
-
-
# 初始化扫把图片列表
-
self.broom_pixmap_list = self.load_broom_pixmaps()
-
self.current_boomGif = QMovie(os.path.join(self.theme_dir, "boom.gif"))
-
self.current_boom = 0
-
self.current_broom_index = 0
-
self.collision_count = 0
-
self.collision_max = 0
-
self.image_name = None
-
self.broom_effect_duration = QPixmap_size
-
self.last_collision_time = 0
-
-
# 初始化窗口属性
-
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowTransparentForInput)
-
self.setAttribute(Qt.WA_TranslucentBackground)
-
self.setGeometry(0, 0, QApplication.desktop().screenGeometry().width(),
-
QApplication.desktop().screenGeometry().height())
-
-
# 初始化gif窗口属性
-
self.gif_label = QLabel(self)
-
self.gif_label.setScaledContents(True)
-
self.gif_label.hide()
-
-
# 创建元素
-
self.snowflakes = set()
-
for _ in range(50):
-
self.snowflakes.add(Snowflake(self.width(), self.height(), self.snowflake_image_paths))
-
-
# 定时器更新动画
-
self.timer = QTimer(self)
-
self.timer.timeout.connect(self.update_snowflakes)
-
self.timer.start(30)
-
-
# 嵌入到桌面窗口
-
desktop_hwnd = get_desktop_window()
-
if desktop_hwnd:
-
self.winId()
-
ctypes.windll.user32.SetParent(int(self.windowHandle().winId()), desktop_hwnd)
-
-
self.mouse_pos = None
-
-
# 初始化配置项
-
self.influence_range = self.config.getint("Settings", "InfluenceRange", fallback=30)
-
self.QPixmap_size = self.config.getint("Settings", "QPixmapSize", fallback=150)
-
-
def load_broom_pixmaps(self):
-
"""加载扫把图片"""
-
broom_dir = get_resource_path(os.path.join("花哨桌面", self.current_theme, "头像"))
-
if not os.path.exists(broom_dir):
-
raise FileNotFoundError(f"头像目录不存在: {broom_dir}")
-
return [
-
QPixmap(os.path.join(broom_dir, f)).scaled(QPixmap_size, QPixmap_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
-
for f in random.sample(
-
[f for f in os.listdir(broom_dir) if f.endswith(".png")],
-
k=len([f for f in os.listdir(broom_dir) if f.endswith(".png")])
-
)
-
]
-
-
def load_themes(self):
-
"""加载所有主题"""
-
themes_dir = get_resource_path("花哨桌面")
-
if not os.path.exists(themes_dir) or not os.path.isdir(themes_dir):
-
raise FileNotFoundError(f"主题目录不存在或路径无效: {themes_dir}")
-
return [d for d in os.listdir(themes_dir) if os.path.isdir(os.path.join(themes_dir, d))]
-
-
def load_theme(self, theme_name):
-
"""加载指定主题"""
-
self.theme_dir = os.path.join(self.base_path, "花哨桌面", theme_name)
-
self.current_theme = theme_name
-
-
# 加载头像和素材
-
self.broom_pixmap_list = self.load_broom_pixmaps()
-
-
# 加载素材目录下的图片
-
self.snowflake_image_paths = [
-
os.path.join(self.theme_dir, "素材", f)
-
for f in os.listdir(os.path.join(self.theme_dir, "素材"))
-
if f.endswith(".png")
-
]
-
-
# 新增:根据配置文件决定是否修改桌面背景
-
if self.config.getboolean("Settings", "ModifyBackground", fallback=True):
-
# 加载 back 文件夹中的图片文件并设置为桌面背景
-
back_dir = os.path.join(self.theme_dir, "back")
-
if os.path.exists(back_dir):
-
back_files = [f for f in os.listdir(back_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp'))]
-
if back_files:
-
back_image_path = os.path.join(back_dir, back_files[0])
-
self.set_desktop_background(back_image_path)
-
-
# 加载 boom.gif
-
self.current_boomGif = QMovie(os.path.join(self.theme_dir, "boom.gif"))
-
self.current_boomGif.start()
-
-
# 重新生成雪花元素
-
self.snowflakes = set()
-
for _ in range(50):
-
self.snowflakes.add(Snowflake(self.width(), self.height(), self.snowflake_image_paths))
-
-
def set_desktop_background(self, image_path):
-
"""使用 Windows API 设置桌面背景"""
-
SPI_SETDESKWALLPAPER = 20
-
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, image_path, 3)
-
-
def init_tray_icon(self):
-
"""初始化系统托盘"""
-
self.tray_icon.setIcon(QIcon(QPixmap("花哨.png"))) # 设置托盘图标
-
self.tray_icon.setToolTip("花哨桌面")
-
-
# 创建托盘菜单
-
menu = QMenu()
-
-
# 主题切换菜单
-
theme_menu = QMenu("切换主题", self)
-
for theme in self.themes:
-
action = QAction(theme, self)
-
action.triggered.connect(lambda _, t=theme: self.switch_theme(t))
-
# 如果当前主题与菜单项一致,在名称前添加选中标记
-
if theme == self.current_theme:
-
action.setText(f"{theme} ✓")
-
theme_menu.addAction(action)
-
menu.addMenu(theme_menu)
-
-
# 开机启动开关
-
self.startup_action = QAction("启用开机启动", self, checkable=True)
-
self.startup_action.setChecked(self.startup_enabled) # 使用配置文件中的值
-
self.startup_action.triggered.connect(self.toggle_startup)
-
menu.addAction(self.startup_action)
-
-
# 新增:桌面背景修改开关
-
self.modify_background_action = QAction("启用桌面背景修改", self, checkable=True)
-
self.modify_background_action.setChecked(self.config.getboolean("Settings", "ModifyBackground", fallback=True))
-
self.modify_background_action.triggered.connect(self.toggle_modify_background)
-
menu.addAction(self.modify_background_action)
-
-
# 添加鼠标影响范围设置
-
influence_range_action = QAction("设置鼠标影响范围", self)
-
influence_range_action.triggered.connect(self.set_influence_range)
-
menu.addAction(influence_range_action)
-
-
# 添加图标大小设置
-
pixmap_size_action = QAction("设置图标大小", self)
-
pixmap_size_action.triggered.connect(self.set_QPixmap_size)
-
menu.addAction(pixmap_size_action)
-
-
exit_action = QAction("退出", self)
-
exit_action.triggered.connect(self.close)
-
menu.addAction(exit_action)
-
-
self.tray_icon.setContextMenu(menu)
-
self.tray_icon.show()
-
-
def switch_theme(self, theme_name):
-
"""切换主题"""
-
self.load_theme(theme_name)
-
self.update()
-
self.update_tray_menu()
-
# 保存当前主题到配置文件
-
self.save_config()
-
-
def update_tray_menu(self):
-
"""更新托盘菜单内容"""
-
menu = self.tray_icon.contextMenu()
-
menu.clear()
-
-
# 主题切换菜单
-
theme_menu = QMenu("切换主题", self)
-
for theme in self.themes:
-
action = QAction(theme, self)
-
action.triggered.connect(lambda _, t=theme: self.switch_theme(t))
-
# 如果当前主题与菜单项一致,在名称前添加选中标记
-
if theme == self.current_theme:
-
action.setText(f"{theme} ✓")
-
theme_menu.addAction(action)
-
menu.addMenu(theme_menu)
-
-
# 开机启动开关
-
self.startup_action = QAction("启用开机启动", self, checkable=True)
-
self.startup_action.setChecked(os.path.exists(os.path.join(winshell.startup(), "花哨桌面.lnk")))
-
self.startup_action.triggered.connect(self.toggle_startup)
-
menu.addAction(self.startup_action)
-
-
# 新增:桌面背景修改开关
-
self.modify_background_action = QAction("启用桌面背景修改", self, checkable=True)
-
self.modify_background_action.setChecked(self.config.getboolean("Settings", "ModifyBackground", fallback=True))
-
self.modify_background_action.triggered.connect(self.toggle_modify_background)
-
menu.addAction(self.modify_background_action)
-
-
# 添加鼠标影响范围设置
-
influence_range_action = QAction("设置鼠标影响范围", self)
-
influence_range_action.triggered.connect(self.set_influence_range)
-
menu.addAction(influence_range_action)
-
-
# 添加图标大小设置
-
pixmap_size_action = QAction("设置图标大小", self)
-
pixmap_size_action.triggered.connect(self.set_QPixmap_size)
-
menu.addAction(pixmap_size_action)
-
-
exit_action = QAction("退出", self)
-
exit_action.triggered.connect(self.close)
-
menu.addAction(exit_action)
-
-
def toggle_startup(self):
-
"""启用/禁用开机启动"""
-
self.startup_enabled = not self.startup_enabled
-
self.update_startup_status()
-
# 保存开机启动状态到配置文件
-
self.save_config()
-
-
def update_startup_status(self):
-
"""更新开机启动状态"""
-
if self.startup_enabled:
-
add_to_startup()
-
else:
-
startup_folder = winshell.startup()
-
shortcut_path = os.path.join(startup_folder, "花哨桌面.lnk")
-
if os.path.exists(shortcut_path):
-
os.remove(shortcut_path)
-
-
def toggle_modify_background(self):
-
"""启用/禁用桌面背景修改"""
-
self.modify_background_enabled = not self.modify_background_enabled
-
self.update_modify_background_status()
-
# 保存桌面背景修改状态到配置文件
-
self.save_config()
-
-
def update_modify_background_status(self):
-
"""更新桌面背景修改状态"""
-
if self.modify_background_enabled:
-
self.load_theme(self.current_theme) # 重新加载主题以应用背景修改
-
else:
-
# 恢复默认桌面背景
-
SPI_SETDESKWALLPAPER = 20
-
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, "", 3)
-
-
def set_influence_range(self):
-
"""设置鼠标影响范围"""
-
new_value, ok = QInputDialog.getInt(self, "设置鼠标影响范围", "请输入新的鼠标影响范围值:", self.influence_range, 20, 50)
-
if ok:
-
self.influence_range = new_value
-
self.save_config()
-
QMessageBox.information(self, "成功", f"鼠标影响范围已设置为 {new_value}")
-
-
def set_QPixmap_size(self):
-
"""设置图标大小"""
-
new_value, ok = QInputDialog.getInt(self, "设置图标大小", "请输入新的图标大小值:", self.QPixmap_size, 50, 200)
-
if ok:
-
self.QPixmap_size = new_value
-
self.save_config()
-
QMessageBox.information(self, "成功", f"图标大小已设置为 {new_value}")
-
-
def save_config(self):
-
"""保存配置到花哨.ini"""
-
if not self.config.has_section("Settings"):
-
self.config.add_section("Settings")
-
self.config.set("Settings", "Theme", self.current_theme)
-
self.config.set("Settings", "Startup", str(self.startup_enabled))
-
self.config.set("Settings", "ModifyBackground", str(self.modify_background_enabled)) # 新增配置项
-
self.config.set("Settings", "InfluenceRange", str(self.influence_range))
-
self.config.set("Settings", "QPixmapSize", str(self.QPixmap_size))
-
with open(self.config_path, "w") as config_file:
-
self.config.write(config_file)
-
-
def play_gif_at_position(self, position):
-
self.gif_label.setMovie(self.current_boomGif)
-
self.gif_label.resize(QPixmap_size, QPixmap_size) # 设置大小
-
self.gif_label.move(position.x(), position.y()) # 移动到指定位置
-
self.current_boomGif.start()
-
self.gif_label.show()
-
# 设置定时器,在 2 秒后隐藏和停止动画
-
QTimer.singleShot(1000, lambda: self.stop_gif(self.current_boomGif))
-
-
def stop_gif(self, movie):
-
movie.stop()
-
self.gif_label.hide()
-
-
def update_snowflakes(self):
-
# 根据 collision_count 计算速度增量
-
speed_increment = (self.collision_count // 10) * 0.5 # 每增加 10,速度增加 0.1
-
# speed_increment = (self.collision_count // 1) * 1
-
for flake in list(self.snowflakes): # 使用 list 复制集合以避免修改时迭代
-
if not flake.move(self.width(), self.height(), self.mouse_pos, speed_increment): # 如果需要销毁
-
self.snowflakes.remove(flake) # 移除
-
self.snowflakes.add(
-
Snowflake(self.width(), self.height(), self.snowflake_image_paths)) # 在顶部生成新的,传递 image_paths 参数
-
self.update() # 触发重绘
-
-
def get_current_time(self):
-
return int(time.time() * 1000) # 毫秒级时间戳
-
-
def paintEvent(self, event):
-
painter = QPainter(self)
-
painter.setRenderHint(QPainter.Antialiasing)
-
# 获取鼠标当前位置
-
mouse_pos = QCursor.pos()
-
mouse_pos = self.mapFromGlobal(mouse_pos)
-
current_broom = self.broom_pixmap_list[self.current_broom_index]
-
# 绘制扫把
-
if self.current_boom == 0:
-
painter.drawPixmap(
-
mouse_pos.x() - current_broom.width() // 2 + 40,
-
mouse_pos.y() + 20,
-
current_broom
-
)
-
else:
-
self.play_gif_at_position(mouse_pos)
-
-
# 绘制元素
-
for flake in self.snowflakes:
-
# 计算距离
-
distance = ((flake.x - mouse_pos.x()) ** 2 + (flake.y - mouse_pos.y()) ** 2) ** 0.5
-
if distance < influence_range: # 鼠标影响范围阈值
-
current_time = self.get_current_time()
-
flake.vx = (flake.x - mouse_pos.x()) * 0.2
-
flake.vy = -(flake.y - mouse_pos.y()) * 0.2
-
flake.x += flake.vx * 3
-
flake.y += flake.vy * 3
-
flake.color.setAlpha(255)
-
self.current_broom_index = (self.current_broom_index + 1) % len(self.broom_pixmap_list)
-
# 基于素材记录碰撞逻辑
-
if current_time - self.last_collision_time > self.broom_effect_duration:
-
name = flake.image_name
-
# print(f"当前素材名称:{name}") # 打印图片名称
-
self.last_collision_time = current_time
-
if "炸弹.png" == name:
-
self.current_boom = 1
-
self.collision_count = 0
-
else:
-
self.current_boom = 0
-
if self.image_name == name:
-
self.collision_count += 1
-
if self.collision_count > self.collision_max:
-
self.collision_max = self.collision_count
-
else:
-
self.image_name = name # 更新上次碰撞的素材标识
-
self.collision_count = 1
-
-
self.update()
-
else:
-
flake.color.setAlpha(200) # 其他时刻保持正常透明度
-
# 绘制元素
-
flake.draw(painter)
-
# 绘制鼠标影响范围的浅浅背景色为圆形
-
painter.setPen(Qt.NoPen) # 不绘制边框
-
painter.setBrush(QColor(255, 255, 255, 50)) # 半透明白色背景
-
-
painter.drawEllipse(
-
mouse_pos.x() - influence_range,
-
mouse_pos.y() - influence_range,
-
influence_range * 2,
-
influence_range * 2
-
)
-
-
# 在窗体中央绘制碰撞次数
-
painter.setPen(QColor(255, 255, 255, 200)) # 透明白色
-
painter.setFont(QFont("Arial", 15))
-
text = f"max: {self.collision_max} speed: {self.collision_count // 10} count: {self.collision_count}"
-
text_rect = painter.boundingRect(self.rect(), Qt.AlignCenter, text)
-
painter.drawText(text_rect, Qt.AlignCenter, text)
-
-
# 捕获鼠标移动事件
-
def mouseMoveEvent(self, event):
-
self.mouse_pos = (event.x(), event.y())
-
-
-
if __name__ == '__main__':
-
add_to_startup()
-
mutex = ctypes.windll.kernel32.CreateMutexW(None, True, "Local/SnowfallProgramMutex")
-
if ctypes.windll.kernel32.GetLastError() == 0x00000010:
-
print("检测到程序已在运行,即将退出...")
-
sys.exit(-1)
-
app = QApplication(sys.argv)
-
w = DynamicWallpaper()
-
w.show()
-
sys.exit(app.exec_())
|