• Python实践项目讲解:如何用制作一个桌面宠物


    制作一个桌面宠物(Desktop Pet)在Python中通常涉及多个步骤,包括创建宠物的图形界面、添加动画效果、处理用户交互等。下面是一个简化的步骤指南,帮助你开始使用Python制作桌面宠物:

    1. 选择图形库
      • Tkinter(Python自带的图形库,简单但功能有限)。
      • Pygame(适用于游戏和多媒体应用,功能强大)。
      • PyQt 或 PySide(跨平台的图形用户界面工具包,用于创建复杂的桌面应用)。
      • 第三方库如Kivy(多平台Python库,用于开发多触摸应用)或wxPython(另一个跨平台的GUI工具包)。
    2. 设计宠物形象
      • 你可以使用图像编辑软件(如Adobe Photoshop、GIMP等)来创建宠物的图片或动画。
      • 宠物可以有不同的状态,比如睡觉、跑动、吃东西等,每种状态对应不同的图片或动画。
    3. 编写代码
      • 初始化图形窗口,并加载宠物的初始状态图片。
      • 编写代码来处理宠物的动画,比如定期更换图片来模拟宠物的动作。
      • 添加用户交互功能,比如用户可以点击或拖动宠物来移动它,或者与宠物进行简单的互动。
    4. 添加逻辑
      • 根据用户的操作或时间的变化,更新宠物的状态和行为。
      • 可以添加一些随机性,使宠物的行为看起来更自然。
    5. 测试与调试
      • 在不同的操作系统和配置上测试你的桌面宠物,确保它能在各种环境下正常工作。
      • 调试并修复任何发现的问题。
    6. 打包与发布
      • 使用如PyInstallercx_Freeze等工具将你的应用打包成一个可执行文件。
      • 发布你的桌面宠物,可以分享到网上供其他人下载和使用。

    运行结果:

    Python代码示例:(代码不完整,完整代码请看文末图片)

    我基本上快发完了,你们先自己试一下能不能写完它

    ps:图片自己可以找,不一定要我的

    1. import sys
    2. import os
    3. import random
    4. from PyQt5 import QtWidgets, QtGui, QtCore
    5. class DeskPet(QtWidgets.QLabel):
    6. def __init__(self):
    7. super().__init__()
    8. self.initUI()
    9. self.childPets = []
    10. self.isDragging = False
    11. self.isMoving = False
    12. self.change = False
    13. def initUI(self):
    14. self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
    15. self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
    16. self.setGeometry(500, 500, 130, 130)
    17. self.currentAction = self.startIdle
    18. self.timer = QtCore.QTimer(self)
    19. self.timer.timeout.connect(self.updateAnimation)
    20. self.changeDirectionTimer = QtCore.QTimer(self) # 添加定时器
    21. self.changeDirectionTimer.timeout.connect(self.changeDirection) # 定时器触发时调用changeDirection方法
    22. self.startIdle()
    23. self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
    24. self.customContextMenuRequested.connect(self.showMenu)
    25. self.setMouseTracking(True)
    26. self.dragging = False
    27. def loadImages(self, path):
    28. return [QtGui.QPixmap(os.path.join(path, f)) for f in os.listdir(path) if f.endswith('.png')]
    29. def startIdle(self):
    30. self.setFixedSize(130, 130)
    31. self.currentAction = self.startIdle
    32. self.images = self.loadImages("Deskpet/resource/xianzhi")
    33. self.currentImage = 0
    34. self.timer.start(100)
    35. self.moveSpeed = 0
    36. self.movingDirection = 0
    37. if self.changeDirectionTimer.isActive():
    38. self.changeDirectionTimer.stop() # 停止方向改变的定时器
    39. def startWalk(self):
    40. self.setFixedSize(130, 130)
    41. if not self.isDragging:
    42. self.currentAction = self.startWalk
    43. direction = random.choice(["zuo", "you"])
    44. self.images = self.loadImages(f"Deskpet/resource/sanbu/{direction}")
    45. self.currentImage = 0
    46. self.movingDirection = -1 if direction == "zuo" else 1
    47. self.moveSpeed = 10
    48. self.timer.start(100)
    49. self.changeDirectionTimer.start(3000) # 启动定时器
    50. def movePet(self):
    51. screen = QtWidgets.QDesktopWidget().screenGeometry()
    52. new_x = self.x() + self.movingDirection * self.moveSpeed
    53. if new_x < 10:
    54. new_x = 10
    55. if self.currentAction == self.startWalk:
    56. self.movingDirection *= -1
    57. # 停止加载原先的图片
    58. self.timer.stop()
    59. self.images = [] # 清空当前图片列表
    60. if self.movingDirection == -1: # 向左移动
    61. self.images = self.loadImages("Deskpet/resource/sanbu/zuo")
    62. else: # 向右移动
    63. self.images = self.loadImages("Deskpet/resource/sanbu/you")
    64. self.currentImage = 0
    65. self.timer.start(100)
    66. elif new_x > screen.width() - self.width() - 10:
    67. new_x = screen.width() - self.width() - 10
    68. if self.currentAction == self.startWalk:
    69. self.movingDirection *= -1
    70. # 停止加载原先的图片
    71. self.timer.stop()
    72. self.images = [] # 清空当前图片列表
    73. # 根据移动方向加载对应的图片
    74. if self.movingDirection == -1: # 向左移动
    75. self.images = self.loadImages("Deskpet/resource/sanbu/zuo")
    76. else: # 向右移动
    77. self.images = self.loadImages("Deskpet/resource/sanbu/you")
    78. self.currentImage = 0
    79. self.timer.start(100)
    80. self.deskpet_rect = self.geometry()
    81. for child in self.childPets:
    82. if isinstance(child, XiaobaiWindow):
    83. self.xiaobai_rect = child.geometry()
    84. if self.deskpet_rect.intersects(self.xiaobai_rect):
    85. child.close()
    86. self.startMeet()
    87. self.move(new_x, self.y())
    88. def startMeet(self):
    89. self.setFixedSize(150, 150)
    90. self.currentAction = self.startMeet
    91. self.images = self.loadImages("Deskpet/resource/meet")
    92. self.currentImage = 0
    93. self.moveSpeed = 0
    94. self.movingDirection = 0
    95. self.timer.start(30)
    96. def startLift(self):
    97. self.setFixedSize(160, 160)
    98. self.currentAction = self.startLift
    99. self.images = self.loadImages("Deskpet/resource/linqi")
    100. self.currentImage = 0
    101. self.moveSpeed = 0
    102. self.movingDirection = 0
    103. self.timer.start(100)
    104. def startFall(self):
    105. self.setFixedSize(150, 150)
    106. self.currentAction = self.startFall
    107. self.images = self.loadImages("Deskpet/resource/xialuo")
    108. self.currentImage = 0
    109. self.movingDirection = 0
    110. self.moveSpeed = 5
    111. self.stopOtherActions()
    112. self.timer.start(30)
    113. def stopOtherActions(self):
    114. self.timer.stop()
    115. if self.currentAction == self.startWalk:
    116. self.changeDirectionTimer.stop() # 停止方向判定定时器
    117. self.startIdle()
    118. elif self.currentAction == self.startLift:
    119. self.startIdle()
    120. elif self.currentAction == self.startFall:
    121. pass
    122. else:
    123. self.startIdle()
    124. def updateAnimation(self):
    125. self.setPixmap(self.images[self.currentImage])
    126. self.currentImage = (self.currentImage + 1) % len(self.images)
    127. if hasattr(self, 'movingDirection'):
    128. if self.currentAction == self.startFall:
    129. self.fallPet()
    130. else:
    131. self.movePet()
    132. def fallPet(self):
    133. self.setFixedSize(130, 130)
    134. screen = QtWidgets.QDesktopWidget().screenGeometry()
    135. new_y = self.y() + self.moveSpeed
    136. if new_y > screen.height() - self.height() - 10:
    137. new_y = screen.height() - self.height() - 10
    138. self.timer.stop()
    139. self.startIdle()
    140. self.move(self.x(), new_y)
    141. def showMenu(self, position):
    142. menu = QtWidgets.QMenu()
    143. if self.currentAction == self.sleep:
    144. menu.addAction("偷吃宵夜", self.Snack)
    145. menu.addAction("唤醒", self.WakeUp)
    146. menu.addSeparator()
    147. menu.addAction("隐藏", self.minimizeWindow)
    148. menu.addAction("退出", self.close)
    149. else:
    150. menu.addAction("散步", self.startWalk)
    151. menu.addAction("下落", self.startFall)
    152. menu.addAction("运动", self.exercise)
    153. menu.addAction("吃饭", self.eating)
    154. menu.addAction("睡觉", self.sleep)
    155. menu.addAction("屁屁舞", self.pipi)
    156. menu.addAction("分身术", self.clonePet)
    157. menu.addAction("动感光波!", self.transform)
    158. menu.addAction("呼唤小白", self.summonXiaobai)
    159. menu.addAction("测试", self.startMeet)
    160. child_menu = menu.addMenu("小彩蛋")
    161. child_menu.addAction("开发者的Q/A", self.starttalk)
    162. child_menu.addAction("小游戏", self.transform)
    163. menu.addSeparator()
    164. menu.addAction("停止", self.startIdle)
    165. menu.addAction("隐藏", self.minimizeWindow)
    166. menu.addAction("退出", self.close)
    167. menu.exec_(self.mapToGlobal(position))
    168. def Snack(self):
    169. self.setFixedSize(160, 130)
    170. self.currentAction = self.sleep
    171. self.images = self.loadImages("Deskpet/resource/snack")
    172. self.currentImage = 0
    173. self.timer.start(100)
    174. self.moveSpeed = 0
    175. self.movingDirection = 0
    176. QtCore.QTimer.singleShot(len(self.images) * 100, self.sleep)
    177. def transform(self):
    178. self.setFixedSize(160, 130)
    179. self.currentAction = self.transform
    180. self.images = self.loadImages("Deskpet/resource/xiandanchaoren")
    181. self.currentImage = 0
    182. self.timer.start(100)
    183. self.moveSpeed = 0
    184. self.movingDirection = 0
    185. def pipi(self):
    186. self.setFixedSize(300, 130)
    187. self.currentAction = self.pipi
    188. self.images = self.loadImages("Deskpet/resource/pipi")
    189. self.currentImage = 0
    190. self.timer.start(25)
    191. self.moveSpeed = 0
    192. self.movingDirection = 0
    193. def exercise(self):
    194. self.setFixedSize(150,180 )
    195. self.currentAction = self.exercise
    196. self.images = self.loadImages("Deskpet/resource/yundong")
    197. self.currentImage = 0
    198. self.timer.start(125)
    199. self.moveSpeed = 0
    200. self.movingDirection = 0
    201. def eating(self):
    202. self.setFixedSize(160, 90)
    203. self.currentAction = self.eating
    204. self.images = self.loadImages("Deskpet/resource/eat")
    205. self.currentImage = 0
    206. self.timer.start(25)
    207. self.moveSpeed = 0
    208. self.movingDirection = 0
    209. QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)
    210. def sleep(self):
    211. self.setFixedSize(315, 500)
    212. self.currentAction = self.sleep
    213. self.images = self.loadImages("Deskpet/resource/sleep")
    214. self.currentImage = 0
    215. self.timer.start(155)
    216. self.moveSpeed = 0
    217. self.movingDirection = 0
    218. def showWakeUpMenu(self):
    219. self.setFixedSize(130, 130)
    220. self.sleeping = True
    221. menu = QtWidgets.QMenu()
    222. menu.addAction("唤醒", self.wakeUp)
    223. menu.exec_(self.mapToGlobal(self.pos()))
    224. def WakeUp(self):
    225. self.setFixedSize(180, 180)
    226. self.sleeping = False
    227. self.currentAction = self.WakeUp
    228. self.images = self.loadImages("Deskpet/resource/waken")
    229. self.currentImage = 0
    230. self.timer.start(30)
    231. # 延时,等待所有图片加载完成
    232. QtCore.QTimer.singleShot(len(self.images) * 30, self.finishWakeUp)
    233. def Ninjia(self):
    234. self.setFixedSize(160, 150)
    235. self.sleeping = False
    236. self.currentAction = self.Ninjia
    237. self.images = self.loadImages("Deskpet/resource/Ninjia")
    238. self.currentImage = 0
    239. self.timer.start(30)
    240. # 延时,等待所有图片加载完成
    241. QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)
    242. def Ninjia2(self):
    243. new_pet = DeskPet()
    244. self.childPets.append(new_pet)
    245. self.setFixedSize(160, 150)
    246. self.sleeping = False
    247. self.currentAction = self.Ninjia2
    248. self.images = self.loadImages("Deskpet/resource/Ninjia2")
    249. self.currentImage = 0
    250. self.timer.start(30)
    251. # 延时,等待所有图片加载完成
    252. QtCore.QTimer.singleShot(len(self.images) * 30, self.startIdle)
    253. def finishWakeUp(self):
    254. self.movingDirection = 0
    255. self.wakeUpImagesLoaded = True
    256. self.setFixedSize(180, 180)
    257. self.timer.stop()
    258. self.currentAction = self.startIdle
    259. self.images = self.loadImages("Deskpet/resource/xianzhi")
    260. self.currentImage = 0
    261. self.timer.start(100)
    262. def clonePet(self):
    263. new_pet = DeskPet()
    264. self.childPets.append(new_pet)
    265. self.Ninjia()
    266. new_pet.show()
    267. new_pet.Ninjia2()
    268. def starttalk(self):
    269. starttalk = ChatApp()
    270. starttalk.show()
    271. self.childPets.append(starttalk)
    272. def summonXiaobai(self):
    273. xiaobai = XiaobaiWindow()
    274. xiaobai.show()
    275. self.childPets.append(xiaobai)
    276. def closeEvent(self, event):
    277. for child in self.childPets:
    278. child.close() # 关闭所有子窗口
    279. super().closeEvent(event)
    280. def minimizeWindow(self):
    281. self.showMinimized()
    282. def mousePressEvent(self, event):
    283. if event.button() == QtCore.Qt.LeftButton:
    284. self.dragging = True
    285. self.isDragging = True
    286. self.drag_position = event.globalPos() - self.pos()
    287. self.prevAction = self.currentAction
    288. self.startLift()
    289. event.accept()
    290. def mouseMoveEvent(self, event):
    291. if QtCore.Qt.LeftButton and self.dragging:
    292. self.move(event.globalPos() - self.drag_position)
    293. event.accept()
    294. def mouseReleaseEvent(self, event):
    295. if event.button() == QtCore.Qt.LeftButton:
    296. self.dragging = False
    297. self.isDragging = False
    298. # 根据需要重新启动changeDirectionTimer
    299. if self.currentAction == self.startWalk:
    300. self.changeDirectionTimer.start()
    301. self.prevAction() # 或者 self.startIdle(), 根据之前的动作恢复状态
    302. event.accept()
    303. def changeDirection(self):
    304. if self.currentAction == self.startFall or self.currentAction == self.eating or self.currentAction == self.transform or self.currentAction == self.sleep or self.currentAction == self.pipi or self.currentAction == self.exercise or self.currentAction == self.WakeUp or self.currentAction == self.startIdle or self.startMeet:
    305. return # 如果正在执行下落动作,不改变方向
    306. if random.random() < 0.5: # 随机选择是否改变方向
    307. self.movingDirection *= -1
    308. self.change = True
    309. if self.change == True:
    310. # 停止加载原先的图片
    311. self.timer.stop()
    312. self.images = [] # 清空当前图片列表
    313. self.startWalk()
    314. self.change = False
    315. class XiaobaiWindow(QtWidgets.QWidget):
    316. def __init__(self):
    317. super().__init__()
    318. self.initUI()
    319. def initUI(self):
    320. self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
    321. self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
    322. self.setGeometry(500, 500, 125, 100)
    323. self.timer = QtCore.QTimer(self)
    324. self.timer.timeout.connect(self.updateAnimation)
    325. self.images = self.loadImages("Deskpet/resource/xiaobai")
    326. self.currentImage = 0
    327. self.timer.start(20)
    328. self.dragPosition = QtCore.QPoint()
    329. self.label = QtWidgets.QLabel(self)
    330. self.label.setGeometry(0, 0, 140, 100)
    331. def mousePressEvent(self, event):
    332. if event.button() == QtCore.Qt.LeftButton:
    333. self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
    334. event.accept()
    335. def mouseMoveEvent(self, event):
    336. if event.buttons() == QtCore.Qt.LeftButton:
    337. self.move(event.globalPos() - self.dragPosition)
    338. event.accept()
    339. def showMenu(self, position):
    340. menu = QtWidgets.QMenu()
    341. menu.addAction("隐藏", self.minimizeWindow)
    342. menu.addAction("回去", self.close)
    343. menu.exec_(self.mapToGlobal(position))
    344. def loadImages(self, path):
    345. return [QtGui.QPixmap(os.path.join(path, f)) for f in os.listdir(path) if f.endswith('.png')]
    346. def updateAnimation(self):
    347. self.label.setPixmap(self.images[self.currentImage])
    348. self.currentImage = (self.currentImage + 1) % len(self.images)
    349. def minimizeWindow(self):
    350. self.showMinimized()
    351. def closeEvent(self, event):
    352. self.timer.stop()
    353. super().closeEvent(event)
    354. def eventFilter(self, obj, event):
    355. if event.type() == QtCore.QEvent.ContextMenu:
    356. self.showMenu(event.pos())
    357. return True
    358. return super().eventFilter(obj, event)
    359. def showEvent(self, event):
    360. self.installEventFilter(self)
    361. class ChatApp(QtWidgets.QWidget):
    362. def __init__(self):
    363. super().__init__()
    364. self.initUI()
    365. def initUI(self):
    366. self.setWindowTitle('聊天窗口')
    367. layout = QtWidgets.QVBoxLayout()
    368. label = QtWidgets.QLabel("你好,我是开发者”乐子猪“\n请问你想问什么?\n(该聊天的内容不完善且功能有缺陷)")
    369. layout.addWidget(label)
    370. button1 = QtWidgets.QPushButton("开发者你是哪里人呀?")
    371. button1.clicked.connect(self.on_button1_clicked)
    372. layout.addWidget(button1)
    373. button2 = QtWidgets.QPushButton("开发者你是一个什么样的人呀?")
    374. button2.clicked.connect(self.on_button2_clicked)
    375. layout.addWidget(button2)
    376. button3 = QtWidgets.QPushButton("我想给开发者生猴子(〃ノωノ)")
    377. layout.addWidget(button3)
    378. self.new_window = None # 新窗口实例作为成员变量
    379. self.setLayout(layout)
    380. def on_button1_clicked(self):
    381. self.new_window = QtWidgets.QWidget()
    382. self.new_window.setWindowTitle('新窗口')
    383. layout = QtWidgets.QVBoxLayout()
    384. label = QtWidgets.QLabel("我是广东人。(不过不是土生土长的)\n#请问你还想聊什么?")
    385. layout.addWidget(label)
    386. button4 = QtWidgets.QPushButton("开发者你喜欢吃什么")
    387. button4.clicked.connect(self.on_button4_clicked)
    388. layout.addWidget(button4)
    389. button3 = QtWidgets.QPushButton("我想给开发者生猴子(〃ノωノ)")
    390. layout.addWidget(button3)
    391. self.new_window.setLayout(layout)
    392. self.new_window.show()
    393. def on_button2_clicked(self):
    394. self.new_window = QtWidgets.QWidget()
    395. self.new_window.setWindowTitle('新窗口')
    396. layout = QtWidgets.QVBoxLayout()
    397. label = QtWidgets.QLabel("一个帅气逼人,温柔可爱,风流倜傥的美男子!\n#请问你还想聊什么?")
    398. layout.addWidget(label)

    完整代码在这里👇↓↓↓

  • 相关阅读:
    Redis缓存(笔记一:缓存介绍和数据库启动)
    矢量图形编辑软件illustrator 2023 mac特点介绍
    TensorRT和Linux MATLAB安装教程(Ubuntu)
    驱动点云格式修改带来的效率提升
    微服务的艺术:构建可扩展和弹性的分布式应用
    Linux-用户和用户组的管理
    Qt实战 数据统计柱状图显示
    FIR和IIR对比以及群延时和相位延时 网站
    Allegro Design Entry HDL(OrCAD Capture HDL)RF-PCB菜单详细介绍
    mysqldump和XBK备份
  • 原文地址:https://blog.csdn.net/m0_65482549/article/details/140015576