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

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 = 外汇跟单gendan5.comQMovie(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_())


请使用浏览器的分享功能分享到微信等