Python期末作业 ---- 桌面挂件宠物小项目

摘要
如今人们都追求美化以及娱乐都会下载一些桌面挂件app以此美化桌面,让桌面看起来更好看更好玩更智能。本项目以此背景设计一个简化版挂件APP,实现在桌面上玩宠物的功能,运行改APP后宠物会一直在桌面上活动,可以通过鼠标拖动宠物到桌面其他地方活动。

1.引言
现如今电脑已经在人们的生活中普遍存在,人们的日常工作生活各方面都已经与电脑息息相关,在使用电脑办公的时候不妨添加点乐趣,所以市面上就出现了各种娱乐小游戏以及各种桌面挂件。
本项目以此设计一个桌面宠物。在日常生活中越来越多人开始养宠物,但是养宠物还是有一定的风险,同时也为了满足那些担心风险以及不敢养宠物的人以此设计一个虚拟宠物,可以让人们在线上也可以养宠物,无论线上线下都可以养自己的宠物,也给日常办公的人在忙碌中带来一丝轻松。同时也可以通过养虚拟宠物培养对动物的爱心。通过线上养宠物,了解动物的各种习性还有爱好,方便自己以后更好地养动物
为了让用户不易形成疲劳感,每次运行的时候都会出现不同的宠物,有60多种宠物随机出现,可以通过鼠标拖动宠物到桌面其他地方活动。

2.系统结构
2.1开发工具及相关模块
开发工具:Python版本:3.8
相关模块:PyQt5模块;以及一些Python自带的模块
2.2 PYQT5介绍
PyQt5是基于Digia公司强大的图形程式框架Qt5的python接口,由一组python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。

PyQt5的类存在与如下模块当中:
● QtCore
QtCore模块涵盖了包的核心的非GUI功能,此模块被用于处理程序中涉及到的 time、文件、目录、数据类型、文本流、链接、mime、线程或进程等对象。
● QtGui
QtGui模块涵盖多种基本图形功能的类; 包括但不限于:窗口集、事件处理、2D图 形、基本的图像和界面 和字体文本。
● QtWidgets
QtWidgets模块包含了一整套UI元素组件,用于建立符合系统风格的classic界面,非常方便,可以在安装时选择是否使用此功能。
● QtMultimedia
QtMultimedia模块包含了一套类库,该类库被用于处理多媒体事件,通过调用API 接口访问摄像头、语音设备、收发消息(radio functionality)等。
● QtBluetooth
QtBluetooth模块包含了处理蓝牙活动的类库,它的功能包括:扫描设备、连接、 交互等行为。
● QtNetwork
QtNetwork模块包含用于网络编程的类库,这组类程序通过提供便捷的TCP/IP 及 UDP 的 c/s 程式码集合,使得基于Qt的网络编程更容易。
● QtPositioning
QtPositioning模块用于获取位置信息,此模块允许使用多种方式达成定位,包括 但不限于:卫星、无线网、文字信息。此应用一般用于网络地图定位系统。
● Enginio
Enginio模块用于构建客户端的应用程式库,用于在运行时访问 Qt Cloud 服务器 托管的应用程序。
● QtWebSockets
QtWebSockets模块包含了一组类程序,用以实现websocket协议。
● QtWebKit
QtWebKit包含了用于实现基于webkit2的网络浏览器的类库。
● QtWebKitWidgets
QtWebKitWidgets模块包含用于基于WebKit1的Web浏览器实现的类,用于基于 QtWidgets的应用程序
● QtXml
QtXml模块包含了用于处理XML的类库,此模块为SAX和DOM API 的实现提供了方 法。
● QtSvg
QtSvg模块通过一组类,为显示矢量图形文件的内容提供了方法。
● QtSql
QtSql模块提供了数据库对象的接口以供使用
● QtTest
QtTest模块包含了可以通过单元测试,以调试PyQt5应用程式的功能。

本项目主要用到QtCore、QtGui、QtWidgets三个模块

2.3程序框架图
Python期末作业 ---- 桌面挂件宠物小项目_第1张图片
2.4程序流程图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200707122554971.png
Python期末作业 ---- 桌面挂件宠物小项目_第2张图片
2.5随机出现的小挂件 —— “宠物”
Python期末作业 ---- 桌面挂件宠物小项目_第3张图片
Python期末作业 ---- 桌面挂件宠物小项目_第4张图片
3.实现代码
3.1首先,我们来初始化一个桌面宠物的窗口组件:

class DesktopPet(QWidget):
def __init__(self, parent=None, **kwargs):
super(DesktopPet, self).__init__(parent)
self.show()

Python期末作业 ---- 桌面挂件宠物小项目_第5张图片
3.2 设置窗口属性

# 初始化
self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint| \
Qt.SubWindow)
self.setAutoFillBackground(False)
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.repaint()

3.3 随机导入一这张图片看看效果

# 随机导入一个宠物
self.pet_images, iconpath = self.randomLoadPetImages()
# 显示当前的图片
self.image = QLabel(self)
self.setImage(self.pet_images[0][0])

3.3随机导入一个宠物的所有图片

def randomLoadPetImages(self):
pet_name = random.choice(list(cfg.PET_ACTIONS_MAP.keys()))
actions = cfg.PET_ACTIONS_MAP[pet_name]
pet_images = []
for action in actions:
pet_images.append([self.loadImage(os.path.join(cfg.ROOT_DIR,\ 			pet_name, 'shime'+item+'.png')) for item inaction])
iconpath = os.path.join(cfg.ROOT_DIR, pet_name, 'shime1.png')
return pet_images, iconpath

3.4随机到桌面上一个位置

def randomPosition(self):
screen_geo = QDesktopWidget().screenGeometry()
pet_geo = self.geometry()
width = (screen_geo.width() - pet_geo.width())* 	random.random()
height = (screen_geo.height() - pet_geo.height()) * 	random.random()
self.move(width, height)

3.5 添加一个托盘图标,以实现桌面宠物程序的退出

# 设置退出选项
quit_action = QAction('退出', self, triggered=self.quit)
quit_action.setIcon(QIcon(iconpath))
self.tray_icon_menu = QMenu(self)
self.tray_icon_menu.addAction(quit_action)
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(QIcon(iconpath))
self.tray_icon.setContextMenu(self.tray_icon_menu)
self.tray_icon.show()

Python期末作业 ---- 桌面挂件宠物小项目_第6张图片
3.6鼠标按下、释放以及拖动

# 鼠标左键按下时, 宠物将和鼠标位置绑定
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.is_follow_mouse = True
self.mouse_drag_pos = event.globalPos() - self.pos()
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor))
# 鼠标移动使宠物移动
def mouseMoveEvent(self, event):
if Qt.LeftButton and self.is_follow_mouse:
self.move(event.globalPos() - self.mouse_drag_pos)
event.accept()
# 鼠标释放,取消绑定
def mouseReleaseEvent(self, event):
self.is_follow_mouse = False
self.setCursor(QCursor(Qt.ArrowCursor))	

3.7 设置定时器使宠物动来动去

# 每隔一段时间做一个动作
self.timer = QTimer()
self.timer.timeout.connect(self.randomAct)
self.timer.start(500)

3.8 实现表情动作的连贯性

# 随机做一个动作
def randomAct(self):
if not self.is_running_action:
self.is_running_action = True
self.action_images = random.choice(self.pet_images)
self.action_max_len = len(self.action_images)
self.action_pointer = 0
self.runFrame()
# 完成动作的每一帧
def runFrame(self):
if self.action_pointer == self.action_max_len:
self.is_running_action = False
self.action_pointer = 0
self.action_max_len = 0
self.setImage(self.action_images[self.action_pointer])
self.action_pointer += 1

3.9 完整代码
DesktopPet.py

import sys
import random
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets, QtGui


'''桌面宠物'''
class DesktopPet(QWidget):
   def __init__(self, parent=None, **kwargs):
      super(DesktopPet, self).__init__(parent)
      # 初始化
      self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
      self.setAutoFillBackground(False)
      self.setAttribute(Qt.WA_TranslucentBackground, True)
      self.repaint()
      # 随机导入一个宠物
      self.pet_images, iconpath = self.randomLoadPetImages()
      # 设置退出选项
      quit_action = QAction('退出', self, triggered=self.quit)
      quit_action.setIcon(QIcon(iconpath))
      self.tray_icon_menu = QMenu(self)
      self.tray_icon_menu.addAction(quit_action)
      self.tray_icon = QSystemTrayIcon(self)
      self.tray_icon.setIcon(QIcon(iconpath))
      self.tray_icon.setContextMenu(self.tray_icon_menu)
      self.tray_icon.show()
      # 当前显示的图片
      self.image = QLabel(self)
      self.setImage(self.pet_images[0][0])
      # 是否跟随鼠标
      self.is_follow_mouse = False
      # 宠物拖拽时避免鼠标直接跳到左上角
      self.mouse_drag_pos = self.pos()
      # 显示
      self.resize(128, 128)
      self.randomPosition()
      self.show()
      # 宠物动画动作执行所需的一些变量
      self.is_running_action = False
      self.action_images = []
      self.action_pointer = 0
      self.action_max_len = 0
      # 每隔一段时间做个动作
      self.timer = QTimer()
      self.timer.timeout.connect(self.randomAct)
      self.timer.start(500)

   '''随机做一个动作'''
   def randomAct(self):
      if not self.is_running_action:
         self.is_running_action = True
         self.action_images = random.choice(self.pet_images)
         self.action_max_len = len(self.action_images)
         self.action_pointer = 0
      self.runFrame()

   '''完成动作的每一帧'''
   def runFrame(self):
      if self.action_pointer == self.action_max_len:
         self.is_running_action = False
         self.action_pointer = 0
         self.action_max_len = 0
      self.setImage(self.action_images[self.action_pointer])
      self.action_pointer += 1

   '''设置当前显示的图片'''
   def setImage(self, image):
      self.image.setPixmap(QPixmap.fromImage(image))

   '''随机导入一个桌面宠物的所有图片'''
   def randomLoadPetImages(self):
      pet_name = random.choice(list(cfg.PET_ACTIONS_MAP.keys()))
      actions = cfg.PET_ACTIONS_MAP[pet_name]
      pet_images = []
      for action in actions:
         pet_images.append([self.loadImage(os.path.join(cfg.ROOT_DIR, pet_name, 'shime'+item+'.png')) for item in action])
      iconpath = os.path.join(cfg.ROOT_DIR, pet_name, 'shime1.png')
      return pet_images, iconpath

   '''鼠标左键按下时, 宠物将和鼠标位置绑定'''
   def mousePressEvent(self, event):
      if event.button() == Qt.LeftButton:
         self.is_follow_mouse = True
         self.mouse_drag_pos = event.globalPos() - self.pos()
         event.accept()
         self.setCursor(QCursor(Qt.OpenHandCursor))

   '''鼠标移动, 则宠物也移动'''
   def mouseMoveEvent(self, event):
      if Qt.LeftButton and self.is_follow_mouse:
         self.move(event.globalPos() - self.mouse_drag_pos)
         event.accept()

   '''鼠标释放时, 取消绑定'''
   def mouseReleaseEvent(self, event):
      self.is_follow_mouse = False
      self.setCursor(QCursor(Qt.ArrowCursor))
      
   '''导入图像'''
   def loadImage(self, imagepath):
      image = QImage()
      image.load(imagepath)
      return image
   
   '''随机到一个屏幕上的某个位置'''
   def randomPosition(self):
      screen_geo = QDesktopWidget().screenGeometry()
      pet_geo = self.geometry()
      width = (screen_geo.width() - pet_geo.width()) * random.random()
      height = (screen_geo.height() - pet_geo.height()) * random.random()
      self.move(width, height)
      
   '''退出程序'''
   def quit(self):
      self.close()
      sys.exit()


'''run'''
if __name__ == '__main__':
   app = QApplication(sys.argv)
   pet = DesktopPet()
   sys.exit(app.exec_())

cfg.py

'''配置文件'''

ROOT_DIR = 'resources'
ACTION_DISTRIBUTION = [['1', '2', '3'],
                  ['4', '5', '6', '7', '8', '9', '10', '11'],
                  ['12', '13', '14'],
                  ['15', '16', '17'],
                  ['18', '19'],
                  ['20', '21'],
                  ['22'],
                  ['23', '24', '25'],
                  ['26',  '27', '28', '29'],
                  ['30', '31', '32', '33'],
                  ['34', '35', '36', '37'],
                  ['38', '39', '40', '41'],
                  ['42', '43', '44', '45', '46']]


PET_ACTIONS_MAP = {
     'pet_1': ACTION_DISTRIBUTION}
for i in range(2, 65):
   PET_ACTIONS_MAP.update({
     'pet_%s' % i: ACTION_DISTRIBUTION})

4.实验
运行结果
Python期末作业 ---- 桌面挂件宠物小项目_第7张图片
5.总结与展望
5.1 总结
该项目主要运用到PyQt5模块,只是实现了在桌面上快速切换图片,并没有太大的设计难度,在设计过程中了解到Qt在python中的运用以及对python程序设计的进一步巩固。

5.2 展望
该项目只实现了最简单的功能,还能在此基础上添加各种功能,例如生长升级,喂食洗澡,放养玩耍等功能,实现类似QQ宠物一样的功能。

你可能感兴趣的:(python)