• 桌面宠物 ① 通过python制作属于自己的桌面宠物


    一、桌面宠物素材

    1.1 需要准备什么素材

            桌面宠物的各种动画效果,可以看作是由一个个GIF动图拼接而成,我们需要准备多组GIF动图来实现桌面宠物的动作切换。

            最好选取是白底的GIF动图。

    1.2 介绍几种获得GIF动图的方式

    1.2.1 通过pr实现视频转GIF

            pr在导出的时候选择动画GIF可以直接导出GIF动图。

            当然了想要白底就需要自已用“蒙版”和画笔工具自己抠图了。

    1.2.2 通过ps实现图片组转GIF

            ps会高级一点,首先点击最上方的窗口,再点击时间轴,在下方显示出的时间轴的最右边的加号可以添加你想要添加的图片。图层右边可以选择删除背景。

            然后选择最上方的文件,选择导出,选择导出为web所用格式旧版,即可

    1.2.3 百度一下,获取网上现成的GIF资源

    ① 百度:“制作GIF动图”

    ② 百度    “GIF动图资源”

    你想要的角色人物素材都在这里!最实用的2d游戏素材! - 知乎

    二、python实现代码

    2.1 目录结构

            项目的目录结构整体如下:main.py为主程序代码。

            normal下的GIF图是宠物平常会随机切换的动作GIF图, click下面的GIF图是点击宠物之后的宠物动作的GIF图

            dialog.txt 记录了宠物的对话信息

             tigerIcon.jpg是缩小到托盘后托盘图标的图片

    2.2 实现代码

    2.2.1 引用包

            os包用于加载文件,sys包用于退出程序,random包用于程序中一些需要调用随机数的操作。其他的三个包则是用于实现桌面宠物的基础。

    1. import os
    2. import sys
    3. import random
    4. from PyQt5.QtGui import *
    5. from PyQt5.QtCore import *
    6. from PyQt5.QtWidgets import *

    2.2.2 主代码部分

    1. if __name__ == '__main__':
    2. # 创建了一个QApplication对象,对象名为app,带两个参数argc,argv
    3. # 所有的PyQt5应用必须创建一个应用(Application)对象。sys.argv参数是一个来自命令行的参数列表。
    4. app = QApplication(sys.argv)
    5. # 窗口组件初始化
    6. pet = DesktopPet()
    7. # 1. 进入时间循环;
    8. # 2. wait,直到响应app可能的输入;
    9. # 3. QT接收和处理用户及系统交代的事件(消息),并传递到各个窗口;
    10. # 4. 程序遇到exit()退出时,机会返回exec()的值。
    11. sys.exit(app.exec_())

    2.2.3 代码运行流程

    整个运行流程为:

    (1)通过self.init():实现窗体的初始化,宠物的GIF图在这个窗体中播放。

    (2)通过self.initPall():配置托盘化

    (3)通过self.initPetImage():将宠物的静态GIF资源,包括对话和GIF动图进行加载

    (4)通过self.petNormalAction():实现宠物随机切换动作和语句的功能

    1. class DesktopPet(QWidget):
    2. def __init__(self, parent=None, **kwargs):
    3. super(DesktopPet, self).__init__(parent)
    4. # 窗体初始化
    5. self.init()
    6. # 托盘化初始
    7. self.initPall()
    8. # 宠物静态gif图加载
    9. self.initPetImage()
    10. # 宠物正常待机,实现随机切换动作
    11. self.petNormalAction()

    ① 加载显示GIF动图的窗体,通过函数init实现,其代码配置如下:

            这几句的作用是对展示宠物的窗体进行一些初步的设置,使得白色GIF图能够去掉背景的白色,将GIF图透明的展示出来

    1. # 窗体初始化
    2. def init(self):
    3. # 初始化
    4. # 设置窗口属性:窗口无标题栏且固定在最前面
    5. # FrameWindowHint:无边框窗口
    6. # WindowStaysOnTopHint: 窗口总显示在最上面
    7. # SubWindow: 新窗口部件是一个子窗口,而无论窗口部件是否有父窗口部件
    8. # https://blog.csdn.net/kaida1234/article/details/79863146
    9. self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
    10. # setAutoFillBackground(True)表示的是自动填充背景,False为透明背景
    11. self.setAutoFillBackground(False)
    12. # 窗口透明,窗体空间不透明
    13. self.setAttribute(Qt.WA_TranslucentBackground, True)
    14. # 重绘组件、刷新
    15. self.repaint()

    ② 实现能托盘显示的功能,通过函数initPall实现,其代码配置如下:

            主要有下面这几个操作:

            (1)读取静态图片资源设置托盘化的图标

             (2)设置托盘化图片点击右键显示的菜单,并对这些菜单的点击操作进行设置

    流程代码如下: 

    1. # 托盘化设置初始化
    2. def initPall(self):
    3. # 导入准备在托盘化显示上使用的图标
    4. icons = os.path.join('tigerIcon.jpg')
    5. # 设置右键显示最小化的菜单项
    6. # 菜单项退出,点击后调用quit函数
    7. quit_action = QAction('退出', self, triggered=self.quit)
    8. # 设置这个点击选项的图片
    9. quit_action.setIcon(QIcon(icons))
    10. # 菜单项显示,点击后调用showing函数
    11. showing = QAction(u'显示', self, triggered=self.showwin)
    12. # 新建一个菜单项控件
    13. self.tray_icon_menu = QMenu(self)
    14. # 在菜单栏添加一个无子菜单的菜单项‘退出’
    15. self.tray_icon_menu.addAction(quit_action)
    16. # 在菜单栏添加一个无子菜单的菜单项‘显示’
    17. self.tray_icon_menu.addAction(showing)
    18. # QSystemTrayIcon类为应用程序在系统托盘中提供一个图标
    19. self.tray_icon = QSystemTrayIcon(self)
    20. # 设置托盘化图标
    21. self.tray_icon.setIcon(QIcon(icons))
    22. # 设置托盘化菜单项
    23. self.tray_icon.setContextMenu(self.tray_icon_menu)
    24. # 展示
    25. self.tray_icon.show()

    其中‘退出’项涉及到的函数代码如下:

    1. # 退出操作,关闭程序
    2. def quit(self):
    3. self.close()
    4. sys.exit()

    其中‘显示’项涉及到的函数代码如下:

    1. # 显示宠物
    2. def showwin(self):
    3. # setWindowOpacity()设置窗体的透明度,通过调整窗体透明度实现宠物的展示和隐藏
    4. self.setWindowOpacity(1)

    ③ 宠物静态资源的加载,通过函数initPetImage实现,其代码配置如下:

            静态资源的加载主要涉及两个部分,对话框内容的加载和图片内容的加载。

    1. # 宠物静态gif图加载
    2. def initPetImage(self):
    3. # 对话框定义
    4. self.talkLabel = QLabel(self)
    5. # 对话框样式设计
    6. self.talkLabel.setStyleSheet("font:15pt '楷体';border-width: 1px;color:blue;")
    7. # 定义显示图片部分
    8. self.image = QLabel(self)
    9. # QMovie是一个可以存放动态视频的类,一般是配合QLabel使用的,可以用来存放GIF动态图
    10. self.movie = QMovie("normal/normal1.gif")
    11. # 设置标签大小
    12. self.movie.setScaledSize(QSize(200, 200))
    13. # 将Qmovie在定义的image中显示
    14. self.image.setMovie(self.movie)
    15. self.movie.start()
    16. self.resize(1024, 1024)
    17. # 调用自定义的randomPosition,会使得宠物出现位置随机
    18. self.randomPosition()
    19. # 展示
    20. self.show()
    21. # https://new.qq.com/rain/a/20211014a002rs00
    22. # 将宠物正常待机状态的动图放入pet1中
    23. self.pet1 = []
    24. for i in os.listdir("normal"):
    25. self.pet1.append("normal/" + i)
    26. # 将宠物正常待机状态的对话放入pet2中
    27. self.dialog = []
    28. # 读取目录下dialog文件
    29. with open("dialog.txt", "r") as f:
    30. text = f.read()
    31. # 以\n 即换行符为分隔符,分割放进dialog中
    32. self.dialog = text.split("\n")

            其中我们希望宠物出现的位置是随机的而不是固定的,那么便通过 randomPosition()实现宠物出现位置的随机。

    1. # 宠物随机位置
    2. def randomPosition(self):
    3. # screenGeometry()函数提供有关可用屏幕几何的信息
    4. screen_geo = QDesktopWidget().screenGeometry()
    5. # 获取窗口坐标系
    6. pet_geo = self.geometry()
    7. width = (screen_geo.width() - pet_geo.width()) * random.random()
    8. height = (screen_geo.height() - pet_geo.height()) * random.random()
    9. self.move(width, height)

    ④ 宠物正常待机,实现随机切换动作,对话框通过函数petNormalAction实现,其代码配置如下

            这里通过QTimer实现定时操作,到达设置的时间即调用相关的函数。其中condition为标识宠物状态的flag,0为平常状态,1为点击状态,这个状态可按照自己的喜好拓展。talk_condition同理,为标识宠物对话状态的flag。

    1. # 宠物正常待机动作
    2. def petNormalAction(self):
    3. # 每隔一段时间做个动作
    4. # 定时器设置
    5. self.timer = QTimer()
    6. # 时间到了自动执行
    7. self.timer.timeout.connect(self.randomAct)
    8. # 动作时间切换设置
    9. self.timer.start(3000)
    10. # 宠物状态设置为正常
    11. self.condition = 0
    12. # 每隔一段时间切换对话
    13. self.talkTimer = QTimer()
    14. self.talkTimer.timeout.connect(self.talk)
    15. self.talkTimer.start(3000)
    16. # 对话状态设置为常态
    17. self.talk_condition = 0
    18. # 宠物对话框
    19. self.talk()

             其中,通过randomAct实现宠物动作的随机切换,通过talk实现对话框内容的切换,其代码如下:

            self.pet1和self.dialog在初始化的时候即定义了。这里可以按照自己的喜好进行拓展,用多个if-else if实现多种状态的切换和定义,增加一些喂食,玩耍动作等。

    1. # 随机动作切换
    2. def randomAct(self):
    3. # condition记录宠物状态,宠物状态为0时,代表正常待机
    4. if not self.condition:
    5. # 随机选择装载在pet1里面的gif图进行展示,实现随机切换
    6. self.movie = QMovie(random.choice(self.pet1))
    7. # 宠物大小
    8. self.movie.setScaledSize(QSize(200, 200))
    9. # 将动画添加到label中
    10. self.image.setMovie(self.movie)
    11. # 开始播放动画
    12. self.movie.start()
    13. # condition不为0,转为切换特有的动作,实现宠物的点击反馈
    14. # 这里可以通过else-if语句往下拓展做更多的交互功能
    15. else:
    16. # 读取特殊状态图片路径
    17. self.movie = QMovie("./click/click.gif")
    18. # 宠物大小
    19. self.movie.setScaledSize(QSize(200, 200))
    20. # 将动画添加到label中
    21. self.image.setMovie(self.movie)
    22. # 开始播放动画
    23. self.movie.start()
    24. # 宠物状态设置为正常待机
    25. self.condition = 0
    26. self.talk_condition = 0
    27. # 宠物对话框行为处理
    28. def talk(self):
    29. if not self.talk_condition:
    30. # talk_condition为0则选取加载在dialog中的语句
    31. self.talkLabel.setText(random.choice(self.dialog))
    32. # 设置样式
    33. self.talkLabel.setStyleSheet(
    34. "font: bold;"
    35. "font:25pt '楷体';"
    36. "color:white;"
    37. "background-color: white"
    38. "url(:/)"
    39. )
    40. # 根据内容自适应大小
    41. self.talkLabel.adjustSize()
    42. else:
    43. # talk_condition为1显示为别点我,这里同样可以通过if-else-if来拓展对应的行为
    44. self.talkLabel.setText("别点我")
    45. self.talkLabel.setStyleSheet(
    46. "font: bold;"
    47. "font:25pt '楷体';"
    48. "color:white;"
    49. "background-color: white"
    50. "url(:/)"
    51. )
    52. self.talkLabel.adjustSize()
    53. # 设置为正常状态
    54. self.talk_condition = 0

    ⑤ 实现能够拖动宠物,通过多个自带函数实现,其代码配置如下:

            实现宠物的拖动主要通过三个函数实现,mouserPressEvent负责在鼠标点击判断其是否在宠物窗口上,如果在则将宠物和鼠标的位置绑定,并执行点击改变宠物GIF图和对话框的操作。

            mouseMoveEvent实现按下后宠物跟着鼠标移动

            mouseReleaseEvent将之前的锁定取消

    1. # 鼠标左键按下时, 宠物将和鼠标位置绑定
    2. def mousePressEvent(self, event):
    3. # 更改宠物状态为点击
    4. self.condition = 1
    5. # 更改宠物对话状态
    6. self.talk_condition = 1
    7. # 即可调用对话状态改变
    8. self.talk()
    9. # 即刻加载宠物点击动画
    10. self.randomAct()
    11. if event.button() == Qt.LeftButton:
    12. self.is_follow_mouse = True
    13. # globalPos() 事件触发点相对于桌面的位置
    14. # pos() 程序相对于桌面左上角的位置,实际是窗口的左上角坐标
    15. self.mouse_drag_pos = event.globalPos() - self.pos()
    16. event.accept()
    17. # 拖动时鼠标图形的设置
    18. self.setCursor(QCursor(Qt.OpenHandCursor))
    19. # 鼠标移动时调用,实现宠物随鼠标移动
    20. def mouseMoveEvent(self, event):
    21. # 如果鼠标左键按下,且处于绑定状态
    22. if Qt.LeftButton and self.is_follow_mouse:
    23. # 宠物随鼠标进行移动
    24. self.move(event.globalPos() - self.mouse_drag_pos)
    25. event.accept()
    26. # 鼠标释放调用,取消绑定
    27. def mouseReleaseEvent(self, event):
    28. self.is_follow_mouse = False
    29. # 鼠标图形设置为箭头
    30. self.setCursor(QCursor(Qt.ArrowCursor))

    ⑥ 实现宠物右键点击具有交互功能,通过函数contextMenuEvent实现,其代码配置如下:

            退出操作通过 qApp.quit()实现,直接退出相应的QT程序。

            隐藏操作则通过self.setWindowOpacity(0)实现,这个可控制窗口的透明度。

    1. # 宠物右键点击交互
    2. def contextMenuEvent(self, event):
    3. # 定义菜单
    4. menu = QMenu(self)
    5. # 定义菜单项
    6. quitAction = menu.addAction("退出")
    7. hide = menu.addAction("隐藏")
    8. # 使用exec_()方法显示菜单。从鼠标右键事件对象中获得当前坐标。mapToGlobal()方法把当前组件的相对坐标转换为窗口(window)的绝对坐标。
    9. action = menu.exec_(self.mapToGlobal(event.pos()))
    10. # 点击事件为退出
    11. if action == quitAction:
    12. qApp.quit()
    13. # 点击事件为隐藏
    14. if action == hide:
    15. # 通过设置透明度方式隐藏宠物
    16. self.setWindowOpacity(0)

    ⑦ 鼠标移到宠物上的时候显示为闭合的手

    1. # 鼠标移进时调用
    2. def enterEvent(self, event):
    3. # 设置鼠标形状 Qt.ClosedHandCursor 非指向手
    4. self.setCursor(Qt.ClosedHandCursor)

    2.3 完整源码

    1. import os
    2. import sys
    3. import random
    4. from PyQt5.QtGui import *
    5. from PyQt5.QtCore import *
    6. from PyQt5.QtWidgets import *
    7. class DesktopPet(QWidget):
    8. def __init__(self, parent=None, **kwargs):
    9. super(DesktopPet, self).__init__(parent)
    10. # 窗体初始化
    11. self.init()
    12. # 托盘化初始
    13. self.initPall()
    14. # 宠物静态gif图加载
    15. self.initPetImage()
    16. # 宠物正常待机,实现随机切换动作
    17. self.petNormalAction()
    18. # 窗体初始化
    19. def init(self):
    20. # 初始化
    21. # 设置窗口属性:窗口无标题栏且固定在最前面
    22. # FrameWindowHint:无边框窗口
    23. # WindowStaysOnTopHint: 窗口总显示在最上面
    24. # SubWindow: 新窗口部件是一个子窗口,而无论窗口部件是否有父窗口部件
    25. # https://blog.csdn.net/kaida1234/article/details/79863146
    26. self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
    27. # setAutoFillBackground(True)表示的是自动填充背景,False为透明背景
    28. self.setAutoFillBackground(False)
    29. # 窗口透明,窗体空间不透明
    30. self.setAttribute(Qt.WA_TranslucentBackground, True)
    31. # 重绘组件、刷新
    32. self.repaint()
    33. # 托盘化设置初始化
    34. def initPall(self):
    35. # 导入准备在托盘化显示上使用的图标
    36. icons = os.path.join('tigerIcon.jpg')
    37. # 设置右键显示最小化的菜单项
    38. # 菜单项退出,点击后调用quit函数
    39. quit_action = QAction('退出', self, triggered=self.quit)
    40. # 设置这个点击选项的图片
    41. quit_action.setIcon(QIcon(icons))
    42. # 菜单项显示,点击后调用showing函数
    43. showing = QAction(u'显示', self, triggered=self.showwin)
    44. # 新建一个菜单项控件
    45. self.tray_icon_menu = QMenu(self)
    46. # 在菜单栏添加一个无子菜单的菜单项‘退出’
    47. self.tray_icon_menu.addAction(quit_action)
    48. # 在菜单栏添加一个无子菜单的菜单项‘显示’
    49. self.tray_icon_menu.addAction(showing)
    50. # QSystemTrayIcon类为应用程序在系统托盘中提供一个图标
    51. self.tray_icon = QSystemTrayIcon(self)
    52. # 设置托盘化图标
    53. self.tray_icon.setIcon(QIcon(icons))
    54. # 设置托盘化菜单项
    55. self.tray_icon.setContextMenu(self.tray_icon_menu)
    56. # 展示
    57. self.tray_icon.show()
    58. # 宠物静态gif图加载
    59. def initPetImage(self):
    60. # 对话框定义
    61. self.talkLabel = QLabel(self)
    62. # 对话框样式设计
    63. self.talkLabel.setStyleSheet("font:15pt '楷体';border-width: 1px;color:blue;")
    64. # 定义显示图片部分
    65. self.image = QLabel(self)
    66. # QMovie是一个可以存放动态视频的类,一般是配合QLabel使用的,可以用来存放GIF动态图
    67. self.movie = QMovie("normal/normal1.gif")
    68. # 设置标签大小
    69. self.movie.setScaledSize(QSize(200, 200))
    70. # 将Qmovie在定义的image中显示
    71. self.image.setMovie(self.movie)
    72. self.movie.start()
    73. self.resize(1024, 1024)
    74. # 调用自定义的randomPosition,会使得宠物出现位置随机
    75. self.randomPosition()
    76. # 展示
    77. self.show()
    78. # https://new.qq.com/rain/a/20211014a002rs00
    79. # 将宠物正常待机状态的动图放入pet1中
    80. self.pet1 = []
    81. for i in os.listdir("normal"):
    82. self.pet1.append("normal/" + i)
    83. # 将宠物正常待机状态的对话放入pet2中
    84. self.dialog = []
    85. # 读取目录下dialog文件
    86. with open("dialog.txt", "r") as f:
    87. text = f.read()
    88. # 以\n 即换行符为分隔符,分割放进dialog中
    89. self.dialog = text.split("\n")
    90. # 宠物正常待机动作
    91. def petNormalAction(self):
    92. # 每隔一段时间做个动作
    93. # 定时器设置
    94. self.timer = QTimer()
    95. # 时间到了自动执行
    96. self.timer.timeout.connect(self.randomAct)
    97. # 动作时间切换设置
    98. self.timer.start(3000)
    99. # 宠物状态设置为正常
    100. self.condition = 0
    101. # 每隔一段时间切换对话
    102. self.talkTimer = QTimer()
    103. self.talkTimer.timeout.connect(self.talk)
    104. self.talkTimer.start(3000)
    105. # 对话状态设置为常态
    106. self.talk_condition = 0
    107. # 宠物对话框
    108. self.talk()
    109. # 随机动作切换
    110. def randomAct(self):
    111. # condition记录宠物状态,宠物状态为0时,代表正常待机
    112. if not self.condition:
    113. # 随机选择装载在pet1里面的gif图进行展示,实现随机切换
    114. self.movie = QMovie(random.choice(self.pet1))
    115. # 宠物大小
    116. self.movie.setScaledSize(QSize(200, 200))
    117. # 将动画添加到label中
    118. self.image.setMovie(self.movie)
    119. # 开始播放动画
    120. self.movie.start()
    121. # condition不为0,转为切换特有的动作,实现宠物的点击反馈
    122. # 这里可以通过else-if语句往下拓展做更多的交互功能
    123. else:
    124. # 读取特殊状态图片路径
    125. self.movie = QMovie("./click/click.gif")
    126. # 宠物大小
    127. self.movie.setScaledSize(QSize(200, 200))
    128. # 将动画添加到label中
    129. self.image.setMovie(self.movie)
    130. # 开始播放动画
    131. self.movie.start()
    132. # 宠物状态设置为正常待机
    133. self.condition = 0
    134. self.talk_condition = 0
    135. # 宠物对话框行为处理
    136. def talk(self):
    137. if not self.talk_condition:
    138. # talk_condition为0则选取加载在dialog中的语句
    139. self.talkLabel.setText(random.choice(self.dialog))
    140. # 设置样式
    141. self.talkLabel.setStyleSheet(
    142. "font: bold;"
    143. "font:25pt '楷体';"
    144. "color:white;"
    145. "background-color: white"
    146. "url(:/)"
    147. )
    148. # 根据内容自适应大小
    149. self.talkLabel.adjustSize()
    150. else:
    151. # talk_condition为1显示为别点我,这里同样可以通过if-else-if来拓展对应的行为
    152. self.talkLabel.setText("别点我")
    153. self.talkLabel.setStyleSheet(
    154. "font: bold;"
    155. "font:25pt '楷体';"
    156. "color:white;"
    157. "background-color: white"
    158. "url(:/)"
    159. )
    160. self.talkLabel.adjustSize()
    161. # 设置为正常状态
    162. self.talk_condition = 0
    163. # 退出操作,关闭程序
    164. def quit(self):
    165. self.close()
    166. sys.exit()
    167. # 显示宠物
    168. def showwin(self):
    169. # setWindowOpacity()设置窗体的透明度,通过调整窗体透明度实现宠物的展示和隐藏
    170. self.setWindowOpacity(1)
    171. # 宠物随机位置
    172. def randomPosition(self):
    173. screen_geo = QDesktopWidget().screenGeometry()
    174. pet_geo = self.geometry()
    175. width = (screen_geo.width() - pet_geo.width()) * random.random()
    176. height = (screen_geo.height() - pet_geo.height()) * random.random()
    177. self.move(width, height)
    178. # 鼠标左键按下时, 宠物将和鼠标位置绑定
    179. def mousePressEvent(self, event):
    180. # 更改宠物状态为点击
    181. self.condition = 1
    182. # 更改宠物对话状态
    183. self.talk_condition = 1
    184. # 即可调用对话状态改变
    185. self.talk()
    186. # 即刻加载宠物点击动画
    187. self.randomAct()
    188. if event.button() == Qt.LeftButton:
    189. self.is_follow_mouse = True
    190. # globalPos() 事件触发点相对于桌面的位置
    191. # pos() 程序相对于桌面左上角的位置,实际是窗口的左上角坐标
    192. self.mouse_drag_pos = event.globalPos() - self.pos()
    193. event.accept()
    194. # 拖动时鼠标图形的设置
    195. self.setCursor(QCursor(Qt.OpenHandCursor))
    196. # 鼠标移动时调用,实现宠物随鼠标移动
    197. def mouseMoveEvent(self, event):
    198. # 如果鼠标左键按下,且处于绑定状态
    199. if Qt.LeftButton and self.is_follow_mouse:
    200. # 宠物随鼠标进行移动
    201. self.move(event.globalPos() - self.mouse_drag_pos)
    202. event.accept()
    203. # 鼠标释放调用,取消绑定
    204. def mouseReleaseEvent(self, event):
    205. self.is_follow_mouse = False
    206. # 鼠标图形设置为箭头
    207. self.setCursor(QCursor(Qt.ArrowCursor))
    208. # 鼠标移进时调用
    209. def enterEvent(self, event):
    210. # 设置鼠标形状 Qt.ClosedHandCursor 非指向手
    211. self.setCursor(Qt.ClosedHandCursor)
    212. # 宠物右键点击交互
    213. def contextMenuEvent(self, event):
    214. # 定义菜单
    215. menu = QMenu(self)
    216. # 定义菜单项
    217. quitAction = menu.addAction("退出")
    218. hide = menu.addAction("隐藏")
    219. # 使用exec_()方法显示菜单。从鼠标右键事件对象中获得当前坐标。mapToGlobal()方法把当前组件的相对坐标转换为窗口(window)的绝对坐标。
    220. action = menu.exec_(self.mapToGlobal(event.pos()))
    221. # 点击事件为退出
    222. if action == quitAction:
    223. qApp.quit()
    224. # 点击事件为隐藏
    225. if action == hide:
    226. # 通过设置透明度方式隐藏宠物
    227. self.setWindowOpacity(0)
    228. if __name__ == '__main__':
    229. # 创建了一个QApplication对象,对象名为app,带两个参数argc,argv
    230. # 所有的PyQt5应用必须创建一个应用(Application)对象。sys.argv参数是一个来自命令行的参数列表。
    231. app = QApplication(sys.argv)
    232. # 窗口组件初始化
    233. pet = DesktopPet()
    234. # 1. 进入时间循环;
    235. # 2. wait,直到响应app可能的输入;
    236. # 3. QT接收和处理用户及系统交代的事件(消息),并传递到各个窗口;
    237. # 4. 程序遇到exit()退出时,机会返回exec()的值。
    238. sys.exit(app.exec_())

    三、程序打包

    3.1 安装pyinstaller

    pip install pyinstaller 
    

    如果提示黄色提示pip版本问题,照着上面的提示修改即可

     3.2 项目目录下完成打包

            进入打开cmd命令行,进入项目目录,输入命令

    pyinstaller -F -w main.py
    

             打包完成后,在生成的dist里面可以看到main.exe文件

             

            这里因为我自己的原因,需要将main.exe放到主目录下才可正常运行

    四、总结与参考资料

    4.1 项目百度网盘:

    链接:https://pan.baidu.com/s/1YYXzGpmCJkz43tYuki1wFQ 
    提取码:3gkw

    DeskTopPetEXE为带打包好的文件。

    DeskTopPet是打包前的文件。

    4.2 总结

    写之前挺开心的,写的时候也挺开心的,写完之后就有点索然无味了。用python做一个简单的桌面宠物,我看到的方法除了我参考的这种加载GIF图外:

    Python 玩出花儿,把罗小黑养在自己桌面_AI科技大本营的博客-CSDN博客

    还有一种通过加载图片帧的方式实现

    Python实现桌面宠物_hxxjxw的博客-CSDN博客_python桌面宠物

    这种通过图片帧的加载实现,需要编写一个自定义配置类cfg.py,很多人也不把这个东西代码给出来:

    1. '''配置文件'''
    2. ROOT_DIR = 'resources'
    3. ACTION_DISTRIBUTION = [['1', '2', '3'],
    4. ['4', '5', '6', '7', '8', '9', '10', '11'],
    5. ['12', '13', '14'],
    6. ['15', '16', '17', '18']]
    7. PET_ACTIONS_MAP = {'pet_1': ACTION_DISTRIBUTION}
    8. for i in range(1, 4):
    9. PET_ACTIONS_MAP.update({'pet_%s' % i: ACTION_DISTRIBUTION})

    这种方式宠物动作的实现,是根据上面这个配置文件进行配置的,比如[1,2,3]就代表这个pet_1文件夹下对应1,2,3号图片组成一个动作。我看到有人直接把这个当作一个动作赋值给宠物,然后图片就会莫名鬼畜。

    纯粹是因为无聊写着玩的,下次再试试能不能弄个3D的🙂

  • 相关阅读:
    java学习第177天,javaWeb学习第36天,p248-255(07/30)
    Linux-笔记 常用命令
    Leetcode 1425: DP + 单调队列
    避免创建不必要的对象
    代码复现: VoxelNet论文和代码解析 pytorch版本(一) train.py
    【MAPBOX基础功能】04、底图加载 - mapbox通过style方式配置其它的底图服务
    怎么查看线程的状态及interrupt优雅的关闭线程和interrupt()、interrupted()、isInterrupted()的作用以及区别在哪?
    下雨天客流量少,美容院怎么做生意
    【mysql 大表清理】磁盘占用太多,清理无效大表
    音频数据如果在中断中会随机给的那就放入队列或者缓冲区;队列缓冲区对音频的作用
  • 原文地址:https://blog.csdn.net/zujiasheng/article/details/124670676