import tkinter # 导入 tkinter GUI 库 import os # 导入 os 库用于文件路径操作 import random # 导入 random 库用于随机选择 from platform import system # 导入系统模块以检测操作系统 from PIL import Image, ImageTk # 导入 Pillow 库用于处理图像透明背景 # 定义一个宠物类 class Pet: def __init__(self): self.root = tkinter.Tk() # 创建窗口 self.delay = 200 # 设置动画帧之间的延迟 (单位:毫秒) self.pixels_from_right = 500 # 宠物初始位置相对于右边的像素 self.pixels_from_bottom = 500 # 宠物初始位置相对于底部的像素 self.move_speed = 3 # 设置宠物移动速度 (单位:像素) # 初始化动画帧数组 self.animation = dict( flower=[self.get_transparent_image('gifs/flower.gif', i) for i in range(55)], # 加载闲置动画帧 eat=[self.get_transparent_image('gifs/eat.gif', i) for i in range(39)], # 加载闲置动画帧 scorn=[self.get_transparent_image('gifs/scorn.gif', i) for i in range(23)], # 加载闲置转睡眠动画帧 sleep=[self.get_transparent_image('gifs/sleep.gif', i) for i in range(36)] * 2, # 加载睡眠动画帧并复制三次 listenmusic=[self.get_transparent_image('gifs/listenmusic.gif', i) for i in range(39)], # 加载左走动画帧 play=[self.get_transparent_image('gifs/play.gif', i) for i in range(60)] # 加载右走动画帧 ) # 窗口配置 self.root.overrideredirect(True) # 移除窗口边框 if system() == 'Windows': self.root.wm_attributes('-transparentcolor', 'white') # 设置 Windows 的透明颜色为白色 else: # 如果是 Mac/Linux self.root.wm_attributes('-transparent', True) # 设置透明属性 self.root.config(bg='systemTransparent') # 设置背景为系统透明 self.root.attributes('-topmost', True) # 确保窗口位于所有其他窗口之上 self.root.bind("<Button-1>", self.onLeftClick) # 绑定左键点击事件 self.root.bind("<Button-3>", self.showpopumenu) # 绑定右键点击事件 self.root.bind("<Key>", self.onKeyPress) # 绑定键盘按键事件 self.root.bind("<B1-Motion>", self.on_drag) # 绑定拖动事件 self.canvas = tkinter.Canvas(self.root, width=100, height=100, bg="white", highlightthickness=0) self.canvas.pack(expand=True) screen_width = self.root.winfo_screenwidth() # 获取屏幕宽度 screen_height = self.root.winfo_screenheight() # 获取屏幕高度 self.min_width = 10 # 设置宠物的最小移动边界 self.max_width = screen_width - 110 # 设置宠物的最大移动边界 # 更改窗口的初始位置 self.curr_width = screen_width - self.pixels_from_right # 当前宽度 self.curr_height = screen_height - self.pixels_from_bottom # 当前高度 self.root.geometry(f"{imgWidth}x{imgHeight}+{self.curr_width}+{self.curr_height}") self.popumenu = tkinter.Menu(self.root, tearoff=False) for animation in self.animation.keys(): self.popumenu.add_command(label=animation, command=lambda anim=animation: self.change_animation(anim)) def get_transparent_image(self, gif_path, index): gif = Image.open(gif_path) gif.seek(index) return ImageTk.PhotoImage(gif.convert('RGBA')) def update(self, i, curr_animation): # 更新窗口状态 self.root.attributes('-topmost', True) # 确保窗口位于最上层 animation_arr = self.animation[curr_animation] # 获取当前动画帧数组 frame = animation_arr[i] # 获取当前帧 self.canvas.delete("all") self.canvas.create_image(50, 50, image=frame) self.canvas.image = frame # 如果需要移动宠物 if curr_animation in ('play', 'scorn'): self.move_window(curr_animation) i += 1 # 指向下一帧 if i == len(animation_arr): # 达到当前动画的末尾,决定下一步动画 next_animation = self.getNextAnimation(curr_animation) self.root.after(self.delay, self.update, 0, next_animation) # 等待一段时间后更新动画 else: self.root.after(self.delay, self.update, i, curr_animation) # 否则继续当前动画 def onLeftClick(self, event): print("检测到左键点击") # 左键点击事件处理函数 def showpopumenu(self, event): self.popumenu.post(event.x_root, event.y_root) def onKeyPress(self, event): if event.char in ('q', 'Q'): self.quit() # 按下 'q' 或 'Q' 键退出程序 def on_drag(self, event): self.curr_width = event.x_root - imgWidth // 2 self.curr_height = event.y_root - imgHeight // 2 self.root.geometry(f"{imgWidth}x{imgHeight}+{self.curr_width}+{self.curr_height}") def move_window(self, curr_animation): if curr_animation == 'play': if self.curr_width > self.min_width: self.curr_width -= self.move_speed # 向左移动 elif curr_animation == 'scorn': if self.curr_width < self.max_width: self.curr_width += self.move_speed # 向右移动 self.root.geometry(f"{imgWidth}x{imgHeight}+{self.curr_width}+{self.curr_height}") # 更新窗口位置 def getNextAnimation(self, curr_animation): # 获取下一个动画类型 if curr_animation == 'flower': return random.choice(['listenmusic', 'eat', 'play', 'scorn', 'sleep']) # 随机选择下一动画 elif curr_animation == 'eat': return random.choice(['listenmusic', 'eat', 'play', 'scorn', 'flower']) elif curr_animation == 'sleep': return random.choice(['listenmusic', 'eat', 'play', 'scorn', 'flower']) # 随机选择保持睡眠或转为闲置 elif curr_animation == 'listenmusic': return random.choice(['sleep', 'eat', 'play', 'scorn', 'flower']) # 转为闲置动画 elif curr_animation == 'play': return random.choice(['listenmusic', 'eat', 'sleep', 'scorn', 'flower']) # 随机选择下一动画 elif curr_animation == 'scorn': return random.choice(['listenmusic', 'eat', 'play', 'sleep', 'flower']) # 随机选择下一动画 elif curr_animation == 'eat': return random.choice(['listenmusic', 'sleep', 'play', 'scorn', 'flower']) # 随机选择下一动画 def change_animation(self, animation): self.update(0, animation) def run(self): self.root.after(self.delay, self.update, 0, 'listenmusic') # 开始时设置为闲置状态 self.root.mainloop() # 启动主事件循环 def quit(self): self.root.destroy() # 销毁窗口,退出程序 if __name__ == '__main__': print('初始化你的桌面宠物...') print('要退出,请右键单击宠物') imgWidth, imgHeight = 100, 100 pet = Pet() # 创建宠物对象 pet.run() # 运行宠物 下面是获取gif动画帧数:
from PIL import Image import os def extract_gif_frames(gif_path, output_folder, picturename): # 打开 GIF 文件 with Image.open(gif_path) as img: frames = [] durations = [] total_duration = 0 # 遍历每一帧 for frame in range(img.n_frames): img.seek(frame) # 定位到当前帧 frames.append(img.copy()) # 复制当前帧 duration = img.info['duration'] / 1000.0 # 获取持续时间(秒) durations.append(duration) total_duration += duration # 累加总持续时间 # 保存每帧为图片,使用指定的 picturename frame_filename = os.path.join(output_folder, f'{picturename}_frame_{frame}.png') img.save(frame_filename) return total_duration, frames, durations # 使用示例 gif_path = r'C:\Users\33947\AppData\Local\Programs\Python\Python39\Scripts\GUI\pet\gifs\brushteeth.gif' output_folder = r'C:\Users\33947\AppData\Local\Programs\Python\Python39\Scripts\GUI\pet\picture\brushteeth' picturename = 'my_gif' # 自定义文件名前缀 os.makedirs(output_folder, exist_ok=True) # 创建输出文件夹 total_duration, frames, durations = extract_gif_frames(gif_path, output_folder, picturename) # 输出总持续时间 print(f"Total duration: {total_duration} seconds")标签:curr,桌宠,width,Python,代码,gif,animation,root,self From: https://blog.csdn.net/m0_66960730/article/details/142341494