共计 12769 个字符,预计需要花费 32 分钟才能阅读完成。
桌面宠物素材
1. 须要筹备什么素材
桌面宠物的各种动画成果,能够看作是由一个个 GIF 动图拼接而成,咱们须要筹备多组 GIF 动图来实现桌面宠物的动作切换。
最好选取是白底的 GIF 动图。
2. 介绍几种取得 GIF 动图的形式
2.1 通过 pr 实现视频转 GIF
pr 在导出的时候抉择动画 GIF 能够间接导出 GIF 动图。
当然了想要白底就须要自已用“蒙版”和画笔工具本人抠图了。
2.2 通过 ps 实现图片组转 GIF
ps 会高级一点,首先点击最上方的窗口,再点击时间轴,在下方显示出的时间轴的最左边的加号能够增加你想要增加的图片。图层左边能够抉择删除背景。
而后抉择最上方的文件,抉择导出,抉择导出为 web 所用格局旧版,即可
2.3 百度一下,获取网上现成的 GIF 资源
① 百度:“制作 GIF 动图”
② 百度“GIF 动图资源”
python 实现代码
1 目录构造
我的项目的目录构造整体如下:main.py 为主程序代码。
normal 下的 GIF 图是宠物平时会随机切换的动作 GIF 图,click 上面的 GIF 图是点击宠物之后的宠物动作的 GIF 图
dialog.txt 记录了宠物的对话信息
tigerIcon.jpg 是放大到托盘后托盘图标的图片
2 实现代码
2.1 援用包
os 包用于加载文件,sys 包用于退出程序,random 包用于程序中一些须要调用随机数的操作。其余的三个包则是用于实现桌面宠物的根底。
import os
import sys
import random
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
2.2 主代码局部
if __name__ == '__main__':
# 创立了一个 QApplication 对象,对象名为 app,带两个参数 argc,argv
# 所有的 PyQt5 利用必须创立一个利用(Application)对象。sys.argv 参数是一个来自命令行的参数列表。app = QApplication(sys.argv)
# 窗口组件初始化
pet = DesktopPet()
# 1. 进入工夫循环;# 2. wait,直到响应 app 可能的输出;# 3. QT 接管和解决用户及零碎交代的事件(音讯),并传递到各个窗口;# 4. 程序遇到 exit() 退出时,机会返回 exec() 的值。sys.exit(app.exec_())
2.3 代码运行流程
整个运行流程为:
(1)通过 self.init():实现窗体的初始化,宠物的 GIF 图在这个窗体中播放。
(2)通过 self.initPall():配置托盘化
(3)通过 self.initPetImage():将宠物的动态 GIF 资源,包含对话和 GIF 动图进行加载
(4)通过 self.petNormalAction():实现宠物随机切换动作和语句的性能
class DesktopPet(QWidget):
def __init__(self, parent=None, **kwargs):
super(DesktopPet, self).__init__(parent)
# 窗体初始化
self.init()
# 托盘化初始
self.initPall()
# 宠物动态 gif 图加载
self.initPetImage()
# 宠物失常待机,实现随机切换动作
self.petNormalAction()
① 加载显示 GIF 动图的窗体,通过函数 init 实现,其代码配置如下:
这几句的作用是对展现宠物的窗体进行一些初步的设置,使得红色 GIF 图可能去掉背景的红色,将 GIF 图通明的展现进去
# 窗体初始化
def init(self):
# 初始化
# 设置窗口属性: 窗口无标题栏且固定在最后面
# FrameWindowHint: 无边框窗口
# WindowStaysOnTopHint: 窗口总显示在最下面
# SubWindow: 新窗口部件是一个子窗口,而无论窗口部件是否有父窗口部件
# https://blog.csdn.net/kaida1234/article/details/79863146
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
# setAutoFillBackground(True) 示意的是主动填充背景,False 为通明背景
self.setAutoFillBackground(False)
# 窗口通明,窗体空间不通明
self.setAttribute(Qt.WA_TranslucentBackground, True)
# 重绘组件、刷新
self.repaint()
② 实现能托盘显示的性能,通过函数 initPall 实现,其代码配置如下:
次要有上面这几个操作:
(1)读取动态图片资源设置托盘化的图标
(2)设置托盘化图片点击右键显示的菜单,并对这些菜单的点击操作进行设置
流程代码如下:
# 托盘化设置初始化
def initPall(self):
# 导入筹备在托盘化显示上应用的图标
icons = os.path.join('tigerIcon.jpg')
# 设置右键显示最小化的菜单项
# 菜单项退出,点击后调用 quit 函数
quit_action = QAction('退出', self, triggered=self.quit)
# 设置这个点击选项的图片
quit_action.setIcon(QIcon(icons))
# 菜单项显示,点击后调用 showing 函数
showing = QAction(u'显示', self, triggered=self.showwin)
# 新建一个菜单项控件
self.tray_icon_menu = QMenu(self)
# 在菜单栏增加一个无子菜单的菜单项‘退出’self.tray_icon_menu.addAction(quit_action)
# 在菜单栏增加一个无子菜单的菜单项‘显示’self.tray_icon_menu.addAction(showing)
# QSystemTrayIcon 类为应用程序在系统托盘中提供一个图标
self.tray_icon = QSystemTrayIcon(self)
# 设置托盘化图标
self.tray_icon.setIcon(QIcon(icons))
# 设置托盘化菜单项
self.tray_icon.setContextMenu(self.tray_icon_menu)
# 展现
self.tray_icon.show()
其中‘退出’项波及到的函数代码如下:
# 退出操作,关闭程序
def quit(self):
self.close()
sys.exit()
其中‘显示’项波及到的函数代码如下:
# 显示宠物
def showwin(self):
# setWindowOpacity()设置窗体的透明度,通过调整窗体透明度实现宠物的展现和暗藏
self.setWindowOpacity(1)
③ 宠物动态资源的加载,通过函数 initPetImage 实现,其代码配置如下:
动态资源的加载次要波及两个局部,对话框内容的加载和图片内容的加载。
# 宠物动态 gif 图加载
def initPetImage(self):
# 对话框定义
self.talkLabel = QLabel(self)
# 对话框款式设计
self.talkLabel.setStyleSheet("font:15pt' 楷体 ';border-width: 1px;color:blue;")
# 定义显示图片局部
self.image = QLabel(self)
# QMovie 是一个能够寄存动静视频的类,个别是配合 QLabel 应用的, 能够用来寄存 GIF 动态图
self.movie = QMovie("normal/normal1.gif")
# 设置标签大小
self.movie.setScaledSize(QSize(200, 200))
# 将 Qmovie 在定义的 image 中显示
self.image.setMovie(self.movie)
self.movie.start()
self.resize(1024, 1024)
# 调用自定义的 randomPosition,会使得宠物呈现地位随机
self.randomPosition()
# 展现
self.show()
# https://new.qq.com/rain/a/20211014a002rs00
# 将宠物失常待机状态的动图放入 pet1 中
self.pet1 = []
for i in os.listdir("normal"):
self.pet1.append("normal/" + i)
# 将宠物失常待机状态的对话放入 pet2 中
self.dialog = []
# 读取目录下 dialog 文件
with open("dialog.txt", "r") as f:
text = f.read()
# 以 \n 即换行符为分隔符,宰割放进 dialog 中
self.dialog = text.split("\n")
其中咱们心愿宠物呈现的地位是随机的而不是固定的,那么便通过 randomPosition() 实现宠物呈现地位的随机。
# 宠物随机地位
def randomPosition(self):
# screenGeometry()函数提供无关可用屏幕几何的信息
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)
④ 宠物失常待机,实现随机切换动作,对话框通过函数 petNormalAction 实现,其代码配置如下
这里通过 QTimer 实现定时操作,达到设置的工夫即调用相干的函数。其中 condition 为标识宠物状态的 flag,0 为平时状态,1 为点击状态,这个状态可依照本人的爱好拓展。talk_condition 同理,为标识宠物对话状态的 flag。
# 宠物失常待机动作
def petNormalAction(self):
# 每隔一段时间做个动作
# 定时器设置
self.timer = QTimer()
# 工夫到了主动执行
self.timer.timeout.connect(self.randomAct)
# 动作工夫切换设置
self.timer.start(3000)
# 宠物状态设置为失常
self.condition = 0
# 每隔一段时间切换对话
self.talkTimer = QTimer()
self.talkTimer.timeout.connect(self.talk)
self.talkTimer.start(3000)
# 对话状态设置为常态
self.talk_condition = 0
# 宠物对话框
self.talk()
其中,通过 randomAct 实现宠物动作的随机切换,通过 talk 实现对话框内容的切换,其代码如下:
self.pet1 和 self.dialog 在初始化的时候即定义了。这里能够依照本人的爱好进行拓展,用多个 if-else if 实现多种状态的切换和定义,减少一些喂食,游玩动作等。
# 随机动作切换
def randomAct(self):
# condition 记录宠物状态,宠物状态为 0 时,代表失常待机
if not self.condition:
# 随机抉择装载在 pet1 外面的 gif 图进行展现,实现随机切换
self.movie = QMovie(random.choice(self.pet1))
# 宠物大小
self.movie.setScaledSize(QSize(200, 200))
# 将动画增加到 label 中
self.image.setMovie(self.movie)
# 开始播放动画
self.movie.start()
# condition 不为 0,转为切换特有的动作,实现宠物的点击反馈
# 这里能够通过 else-if 语句往下拓展做更多的交互性能
else:
# 读取非凡状态图片门路
self.movie = QMovie("./click/click.gif")
# 宠物大小
self.movie.setScaledSize(QSize(200, 200))
# 将动画增加到 label 中
self.image.setMovie(self.movie)
# 开始播放动画
self.movie.start()
# 宠物状态设置为失常待机
self.condition = 0
self.talk_condition = 0
# 宠物对话框行为解决
def talk(self):
if not self.talk_condition:
# talk_condition 为 0 则选取加载在 dialog 中的语句
self.talkLabel.setText(random.choice(self.dialog))
# 设置款式
self.talkLabel.setStyleSheet(
"font: bold;"
"font:25pt' 楷体 ';"
"color:white;"
"background-color: white"
"url(:/)"
)
# 依据内容自适应大小
self.talkLabel.adjustSize()
else:
# talk_condition 为 1 显示为别点我,这里同样能够通过 if-else-if 来拓展对应的行为
self.talkLabel.setText("别点我")
self.talkLabel.setStyleSheet(
"font: bold;"
"font:25pt' 楷体 ';"
"color:white;"
"background-color: white"
"url(:/)"
)
self.talkLabel.adjustSize()
# 设置为失常状态
self.talk_condition = 0
⑤ 实现可能拖动宠物,通过多个自带函数实现,其代码配置如下:
实现宠物的拖动次要通过三个函数实现,mouserPressEvent 负责在鼠标点击判断其是否在宠物窗口上,如果在则将宠物和鼠标的地位绑定,并执行点击扭转宠物 GIF 图和对话框的操作。
mouseMoveEvent 实现按下后宠物跟着鼠标挪动
mouseReleaseEvent 将之前的锁定勾销
# 鼠标左键按下时, 宠物将和鼠标地位绑定
def mousePressEvent(self, event):
# 更改宠物状态为点击
self.condition = 1
# 更改宠物对话状态
self.talk_condition = 1
# 即可调用对话状态扭转
self.talk()
# 即刻加载宠物点击动画
self.randomAct()
if event.button() == Qt.LeftButton:
self.is_follow_mouse = True
# globalPos() 事件触发点绝对于桌面的地位
# pos() 程序绝对于桌面左上角的地位,理论是窗口的左上角坐标
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))
⑥ 实现宠物右键点击具备交互性能,通过函数 contextMenuEvent 实现,其代码配置如下:
退出操作通过 qApp.quit() 实现,间接退出相应的 QT 程序。
暗藏操作则通过 self.setWindowOpacity(0) 实现,这个可管制窗口的透明度。
# 宠物右键点击交互
def contextMenuEvent(self, event):
# 定义菜单
menu = QMenu(self)
# 定义菜单项
quitAction = menu.addAction("退出")
hide = menu.addAction("暗藏")
# 应用 exec_() 办法显示菜单。从鼠标右键事件对象中取得以后坐标。mapToGlobal() 办法把以后组件的绝对坐标转换为窗口(window)的相对坐标。action = menu.exec_(self.mapToGlobal(event.pos()))
# 点击事件为退出
if action == quitAction:
qApp.quit()
# 点击事件为暗藏
if action == hide:
# 通过设置透明度形式暗藏宠物
self.setWindowOpacity(0)
⑦ 鼠标移到宠物上的时候显示为闭合的手
# 鼠标移进时调用
def enterEvent(self, event):
# 设置鼠标形态 Qt.ClosedHandCursor 非指向手
self.setCursor(Qt.ClosedHandCursor)
3 残缺源码
import os
import sys
import random
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class DesktopPet(QWidget):
def __init__(self, parent=None, **kwargs):
super(DesktopPet, self).__init__(parent)
# 窗体初始化
self.init()
# 托盘化初始
self.initPall()
# 宠物动态 gif 图加载
self.initPetImage()
# 宠物失常待机,实现随机切换动作
self.petNormalAction()
# 窗体初始化
def init(self):
# 初始化
# 设置窗口属性: 窗口无标题栏且固定在最后面
# FrameWindowHint: 无边框窗口
# WindowStaysOnTopHint: 窗口总显示在最下面
# SubWindow: 新窗口部件是一个子窗口,而无论窗口部件是否有父窗口部件
# https://blog.csdn.net/kaida1234/article/details/79863146
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
# setAutoFillBackground(True) 示意的是主动填充背景,False 为通明背景
self.setAutoFillBackground(False)
# 窗口通明,窗体空间不通明
self.setAttribute(Qt.WA_TranslucentBackground, True)
# 重绘组件、刷新
self.repaint()
# 托盘化设置初始化
def initPall(self):
# 导入筹备在托盘化显示上应用的图标
icons = os.path.join('tigerIcon.jpg')
# 设置右键显示最小化的菜单项
# 菜单项退出,点击后调用 quit 函数
quit_action = QAction('退出', self, triggered=self.quit)
# 设置这个点击选项的图片
quit_action.setIcon(QIcon(icons))
# 菜单项显示,点击后调用 showing 函数
showing = QAction(u'显示', self, triggered=self.showwin)
# 新建一个菜单项控件
self.tray_icon_menu = QMenu(self)
# 在菜单栏增加一个无子菜单的菜单项‘退出’self.tray_icon_menu.addAction(quit_action)
# 在菜单栏增加一个无子菜单的菜单项‘显示’self.tray_icon_menu.addAction(showing)
# QSystemTrayIcon 类为应用程序在系统托盘中提供一个图标
self.tray_icon = QSystemTrayIcon(self)
# 设置托盘化图标
self.tray_icon.setIcon(QIcon(icons))
# 设置托盘化菜单项
self.tray_icon.setContextMenu(self.tray_icon_menu)
# 展现
self.tray_icon.show()
# 宠物动态 gif 图加载
def initPetImage(self):
# 对话框定义
self.talkLabel = QLabel(self)
# 对话框款式设计
self.talkLabel.setStyleSheet("font:15pt' 楷体 ';border-width: 1px;color:blue;")
# 定义显示图片局部
self.image = QLabel(self)
# QMovie 是一个能够寄存动静视频的类,个别是配合 QLabel 应用的, 能够用来寄存 GIF 动态图
self.movie = QMovie("normal/normal1.gif")
# 设置标签大小
self.movie.setScaledSize(QSize(200, 200))
# 将 Qmovie 在定义的 image 中显示
self.image.setMovie(self.movie)
self.movie.start()
self.resize(1024, 1024)
# 调用自定义的 randomPosition,会使得宠物呈现地位随机
self.randomPosition()
# 展现
self.show()
# https://new.qq.com/rain/a/20211014a002rs00
# 将宠物失常待机状态的动图放入 pet1 中
self.pet1 = []
for i in os.listdir("normal"):
self.pet1.append("normal/" + i)
# 将宠物失常待机状态的对话放入 pet2 中
self.dialog = []
# 读取目录下 dialog 文件
with open("dialog.txt", "r") as f:
text = f.read()
# 以 \n 即换行符为分隔符,宰割放进 dialog 中
self.dialog = text.split("\n")
# 宠物失常待机动作
def petNormalAction(self):
# 每隔一段时间做个动作
# 定时器设置
self.timer = QTimer()
# 工夫到了主动执行
self.timer.timeout.connect(self.randomAct)
# 动作工夫切换设置
self.timer.start(3000)
# 宠物状态设置为失常
self.condition = 0
# 每隔一段时间切换对话
self.talkTimer = QTimer()
self.talkTimer.timeout.connect(self.talk)
self.talkTimer.start(3000)
# 对话状态设置为常态
self.talk_condition = 0
# 宠物对话框
self.talk()
# 随机动作切换
def randomAct(self):
# condition 记录宠物状态,宠物状态为 0 时,代表失常待机
if not self.condition:
# 随机抉择装载在 pet1 外面的 gif 图进行展现,实现随机切换
self.movie = QMovie(random.choice(self.pet1))
# 宠物大小
self.movie.setScaledSize(QSize(200, 200))
# 将动画增加到 label 中
self.image.setMovie(self.movie)
# 开始播放动画
self.movie.start()
# condition 不为 0,转为切换特有的动作,实现宠物的点击反馈
# 这里能够通过 else-if 语句往下拓展做更多的交互性能
else:
# 读取非凡状态图片门路
self.movie = QMovie("./click/click.gif")
# 宠物大小
self.movie.setScaledSize(QSize(200, 200))
# 将动画增加到 label 中
self.image.setMovie(self.movie)
# 开始播放动画
self.movie.start()
# 宠物状态设置为失常待机
self.condition = 0
self.talk_condition = 0
# 宠物对话框行为解决
def talk(self):
if not self.talk_condition:
# talk_condition 为 0 则选取加载在 dialog 中的语句
self.talkLabel.setText(random.choice(self.dialog))
# 设置款式
self.talkLabel.setStyleSheet(
"font: bold;"
"font:25pt' 楷体 ';"
"color:white;"
"background-color: white"
"url(:/)"
)
# 依据内容自适应大小
self.talkLabel.adjustSize()
else:
# talk_condition 为 1 显示为别点我,这里同样能够通过 if-else-if 来拓展对应的行为
self.talkLabel.setText("别点我")
self.talkLabel.setStyleSheet(
"font: bold;"
"font:25pt' 楷体 ';"
"color:white;"
"background-color: white"
"url(:/)"
)
self.talkLabel.adjustSize()
# 设置为失常状态
self.talk_condition = 0
# 退出操作,关闭程序
def quit(self):
self.close()
sys.exit()
# 显示宠物
def showwin(self):
# setWindowOpacity()设置窗体的透明度,通过调整窗体透明度实现宠物的展现和暗藏
self.setWindowOpacity(1)
# 宠物随机地位
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 mousePressEvent(self, event):
# 更改宠物状态为点击
self.condition = 1
# 更改宠物对话状态
self.talk_condition = 1
# 即可调用对话状态扭转
self.talk()
# 即刻加载宠物点击动画
self.randomAct()
if event.button() == Qt.LeftButton:
self.is_follow_mouse = True
# globalPos() 事件触发点绝对于桌面的地位
# pos() 程序绝对于桌面左上角的地位,理论是窗口的左上角坐标
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 enterEvent(self, event):
# 设置鼠标形态 Qt.ClosedHandCursor 非指向手
self.setCursor(Qt.ClosedHandCursor)
# 宠物右键点击交互
def contextMenuEvent(self, event):
# 定义菜单
menu = QMenu(self)
# 定义菜单项
quitAction = menu.addAction("退出")
hide = menu.addAction("暗藏")
# 应用 exec_() 办法显示菜单。从鼠标右键事件对象中取得以后坐标。mapToGlobal() 办法把以后组件的绝对坐标转换为窗口(window)的相对坐标。action = menu.exec_(self.mapToGlobal(event.pos()))
# 点击事件为退出
if action == quitAction:
qApp.quit()
# 点击事件为暗藏
if action == hide:
# 通过设置透明度形式暗藏宠物
self.setWindowOpacity(0)
if __name__ == '__main__':
# 创立了一个 QApplication 对象,对象名为 app,带两个参数 argc,argv
# 所有的 PyQt5 利用必须创立一个利用(Application)对象。sys.argv 参数是一个来自命令行的参数列表。app = QApplication(sys.argv)
# 窗口组件初始化
pet = DesktopPet()
# 1. 进入工夫循环;# 2. wait,直到响应 app 可能的输出;# 3. QT 接管和解决用户及零碎交代的事件(音讯),并传递到各个窗口;# 4. 程序遇到 exit() 退出时,机会返回 exec() 的值。sys.exit(app.exec_())
程序打包
1 装置 pyinstaller
pip install pyinstaller
如果提醒黄色提醒 pip 版本问题,照着下面的提醒批改即可
2 我的项目目录下实现打包
进入关上 cmd 命令行,进入我的项目目录,输出命令
pyinstaller -F -w main.py
打包实现后,在生成的 dist 外面能够看到 main.exe 文件
这里因为我本人的起因,须要将 main.exe 放到主目录下才可失常运行
最近我破费了几天的工夫,整顿了 1 份实践 + 实际的 Python 入门进阶教程,这或者是你见过十分好的一份学习材料之一。独家打造、完全免费,须要的同学能够关注 gzh【Python 编程学习圈】,发送“ 学习材料 ”获取~