Python 可輕松制作屬于自己的桌面寵物!
↓推薦關(guān)注↓
來源:blog.csdn.net/zujiasheng?type=blog
一、桌面寵物素材
1.1 需要準(zhǔn)備什么素材
桌面寵物的各種動畫效果,可以看作是由一個個GIF動圖拼接而成,我們需要準(zhǔn)備多組GIF動圖來實現(xiàn)桌面寵物的動作切換。

1.2 介紹幾種獲得GIF動圖的方式
1.2.1 通過pr實現(xiàn)視頻轉(zhuǎn)GIF

pr在導(dǎo)出的時候選擇動畫GIF可以直接導(dǎo)出GIF動圖。
當(dāng)然了想要白底就需要自已用“蒙版”和畫筆工具自己摳圖了。
1.2.2 通過ps實現(xiàn)圖片組轉(zhuǎn)GIF
ps會高級一點,首先點擊最上方的窗口,再點擊時間軸,在下方顯示出的時間軸的最右邊的加號可以添加你想要添加的圖片。圖層右邊可以選擇刪除背景。

然后選擇最上方的文件,選擇導(dǎo)出,選擇導(dǎo)出為web所用格式舊版,即可


1.2.3 百度一下,獲取網(wǎng)上現(xiàn)成的GIF資源
① 百度:“制作GIF動圖”
② 百度 ? ?“GIF動圖資源”
你想要的角色人物素材都在這里!最實用的2d游戲素材!- 知乎:
https://zhuanlan.zhihu.com/p/408992668
二、Python實現(xiàn)代碼

2.1 目錄結(jié)構(gòu)
項目的目錄結(jié)構(gòu)整體如下:main.py為主程序代碼。

normal下的GIF圖是寵物平常會隨機切換的動作GIF圖, click下面的GIF圖是點擊寵物之后的寵物動作的GIF圖

dialog.txt 記錄了寵物的對話信息

tigerIcon.jpg是縮小到托盤后托盤圖標(biāo)的圖片

2.2 實現(xiàn)代碼
2.2.1 引用包
os包用于加載文件,sys包用于退出程序,random包用于程序中一些需要調(diào)用隨機數(shù)的操作。其他的三個包則是用于實現(xiàn)桌面寵物的基礎(chǔ)。
import?os
import?sys
import?random
from?PyQt5.QtGui?import?*
from?PyQt5.QtCore?import?*
from?PyQt5.QtWidgets?import?*
2.2.2 主代碼部分
if?__name__?==?'__main__':
????#?創(chuàng)建了一個QApplication對象,對象名為app,帶兩個參數(shù)argc,argv
????#?所有的PyQt5應(yīng)用必須創(chuàng)建一個應(yīng)用(Application)對象。sys.argv參數(shù)是一個來自命令行的參數(shù)列表。
????app?=?QApplication(sys.argv)
????#?窗口組件初始化
????pet?=?DesktopPet()
????# 1. 進入時間循環(huán);
????# 2. wait,直到響應(yīng)app可能的輸入;
????# 3. QT接收和處理用戶及系統(tǒng)交代的事件(消息),并傳遞到各個窗口;
????# 4. 程序遇到exit()退出時,機會返回exec()的值。
????sys.exit(app.exec_())
2.2.3 代碼運行流程
整個運行流程為:
(1)通過self.init():實現(xiàn)窗體的初始化,寵物的GIF圖在這個窗體中播放。
(2)通過self.initPall():配置托盤化
(3)通過self.initPetImage():將寵物的靜態(tài)GIF資源,包括對話和GIF動圖進行加載
(4)通過self.petNormalAction():實現(xiàn)寵物隨機切換動作和語句的功能
class?DesktopPet(QWidget):
????def?__init__(self,?parent=None,?**kwargs):
????????super(DesktopPet,?self).__init__(parent)
????????#?窗體初始化
????????self.init()
????????#?托盤化初始
????????self.initPall()
????????#?寵物靜態(tài)gif圖加載
????????self.initPetImage()
????????#?寵物正常待機,實現(xiàn)隨機切換動作
????????self.petNormalAction()
① 加載顯示GIF動圖的窗體,通過函數(shù)init實現(xiàn),其代碼配置如下:
這幾句的作用是對展示寵物的窗體進行一些初步的設(shè)置,使得白色GIF圖能夠去掉背景的白色,將GIF圖透明的展示出來
????#?窗體初始化
????def?init(self):
????????#?初始化
????????#?設(shè)置窗口屬性:窗口無標(biāo)題欄且固定在最前面
????????#?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()
② 實現(xiàn)能托盤顯示的功能,通過函數(shù)initPall實現(xiàn),其代碼配置如下:
主要有下面這幾個操作:
(1)讀取靜態(tài)圖片資源設(shè)置托盤化的圖標(biāo)

(2)設(shè)置托盤化圖片點擊右鍵顯示的菜單,并對這些菜單的點擊操作進行設(shè)置

流程代碼如下:
?#?托盤化設(shè)置初始化
????def?initPall(self):
????????#?導(dǎo)入準(zhǔn)備在托盤化顯示上使用的圖標(biāo)
????????icons?=?os.path.join('tigerIcon.jpg')
????????#?設(shè)置右鍵顯示最小化的菜單項
????????#?菜單項退出,點擊后調(diào)用quit函數(shù)
????????quit_action?=?QAction('退出',?self,?triggered=self.quit)
????????#?設(shè)置這個點擊選項的圖片
????????quit_action.setIcon(QIcon(icons))
????????#?菜單項顯示,點擊后調(diào)用showing函數(shù)
????????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類為應(yīng)用程序在系統(tǒng)托盤中提供一個圖標(biāo)
????????self.tray_icon?=?QSystemTrayIcon(self)
????????#?設(shè)置托盤化圖標(biāo)
????????self.tray_icon.setIcon(QIcon(icons))
????????#?設(shè)置托盤化菜單項
????????self.tray_icon.setContextMenu(self.tray_icon_menu)
????????#?展示
????????self.tray_icon.show()
其中‘退出’項涉及到的函數(shù)代碼如下:
????#?退出操作,關(guān)閉程序
????def?quit(self):
????????self.close()
????????sys.exit()
其中‘顯示’項涉及到的函數(shù)代碼如下:
????#?顯示寵物
????def?showwin(self):
????????#?setWindowOpacity()設(shè)置窗體的透明度,通過調(diào)整窗體透明度實現(xiàn)寵物的展示和隱藏
????????self.setWindowOpacity(1)
③ 寵物靜態(tài)資源的加載,通過函數(shù)initPetImage實現(xiàn),其代碼配置如下:
靜態(tài)資源的加載主要涉及兩個部分,對話框內(nèi)容的加載和圖片內(nèi)容的加載。
????#?寵物靜態(tài)gif圖加載
????def?initPetImage(self):
????????#?對話框定義
????????self.talkLabel?=?QLabel(self)
????????#?對話框樣式設(shè)計
????????self.talkLabel.setStyleSheet("font:15pt?'楷體';border-width:?1px;color:blue;")?
????????#?定義顯示圖片部分
????????self.image?=?QLabel(self)
????????#?QMovie是一個可以存放動態(tài)視頻的類,一般是配合QLabel使用的,可以用來存放GIF動態(tài)圖
????????self.movie?=?QMovie("normal/normal1.gif")
????????#?設(shè)置標(biāo)簽大小
????????self.movie.setScaledSize(QSize(200,?200))
????????#?將Qmovie在定義的image中顯示
????????self.image.setMovie(self.movie)
????????self.movie.start()
????????self.resize(1024,?1024)
????????#?調(diào)用自定義的randomPosition,會使得寵物出現(xiàn)位置隨機
????????self.randomPosition()
????????#?展示
????????self.show()
????????#?https://new.qq.com/rain/a/20211014a002rs00
????????#?將寵物正常待機狀態(tài)的動圖放入pet1中
????????self.pet1?=?[]
????????for?i?in?os.listdir("normal"):
????????????self.pet1.append("normal/"?+?i)
????????#?將寵物正常待機狀態(tài)的對話放入pet2中
????????self.dialog?=?[]
????????#?讀取目錄下dialog文件
????????with?open("dialog.txt",?"r")?as?f:
????????????text?=?f.read()
????????????#?以\n?即換行符為分隔符,分割放進dialog中
????????????self.dialog?=?text.split("\n")
其中我們希望寵物出現(xiàn)的位置是隨機的而不是固定的,那么便通過 randomPosition()實現(xiàn)寵物出現(xiàn)位置的隨機。
????#?寵物隨機位置
????def?randomPosition(self):
????????#?screenGeometry()函數(shù)提供有關(guān)可用屏幕幾何的信息
????????screen_geo?=?QDesktopWidget().screenGeometry()
????????#?獲取窗口坐標(biāo)系
????????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)
④ 寵物正常待機,實現(xiàn)隨機切換動作,對話框通過函數(shù)petNormalAction實現(xiàn),其代碼配置如下
這里通過QTimer實現(xiàn)定時操作,到達(dá)設(shè)置的時間即調(diào)用相關(guān)的函數(shù)。其中condition為標(biāo)識寵物狀態(tài)的flag,0為平常狀態(tài),1為點擊狀態(tài),這個狀態(tài)可按照自己的喜好拓展。talk_condition同理,為標(biāo)識寵物對話狀態(tài)的flag。
#?寵物正常待機動作
????def?petNormalAction(self):
????????#?每隔一段時間做個動作
????????#?定時器設(shè)置
????????self.timer?=?QTimer()
????????#?時間到了自動執(zhí)行
????????self.timer.timeout.connect(self.randomAct)
????????#?動作時間切換設(shè)置
????????self.timer.start(3000)
????????#?寵物狀態(tài)設(shè)置為正常
????????self.condition?=?0
????????#?每隔一段時間切換對話
????????self.talkTimer?=?QTimer()
????????self.talkTimer.timeout.connect(self.talk)
????????self.talkTimer.start(3000)
????????#?對話狀態(tài)設(shè)置為常態(tài)
????????self.talk_condition?=?0
????????#?寵物對話框
????????self.talk()
其中,通過randomAct實現(xiàn)寵物動作的隨機切換,通過talk實現(xiàn)對話框內(nèi)容的切換,其代碼如下:
self.pet1和self.dialog在初始化的時候即定義了。這里可以按照自己的喜好進行拓展,用多個if-else if實現(xiàn)多種狀態(tài)的切換和定義,增加一些喂食,玩耍動作等。
?#?隨機動作切換
????def?randomAct(self):
????????#?condition記錄寵物狀態(tài),寵物狀態(tài)為0時,代表正常待機
????????if?not?self.condition:
????????????#?隨機選擇裝載在pet1里面的gif圖進行展示,實現(xiàn)隨機切換
????????????self.movie?=?QMovie(random.choice(self.pet1))
????????????#?寵物大小
????????????self.movie.setScaledSize(QSize(200,?200))
????????????#?將動畫添加到label中
????????????self.image.setMovie(self.movie)
????????????#?開始播放動畫
????????????self.movie.start()
????????#?condition不為0,轉(zhuǎn)為切換特有的動作,實現(xiàn)寵物的點擊反饋
????????#?這里可以通過else-if語句往下拓展做更多的交互功能
????????else:
????????????#?讀取特殊狀態(tài)圖片路徑
????????????self.movie?=?QMovie("./click/click.gif")
????????????#?寵物大小
????????????self.movie.setScaledSize(QSize(200,?200))
????????????#?將動畫添加到label中
????????????self.image.setMovie(self.movie)
????????????#?開始播放動畫
????????????self.movie.start()
????????????#?寵物狀態(tài)設(shè)置為正常待機
????????????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))
????????????#?設(shè)置樣式
????????????self.talkLabel.setStyleSheet(
????????????????"font:?bold;"
????????????????"font:25pt?'楷體';"
????????????????"color:white;"
????????????????"background-color:?white"
????????????????"url(:/)"
????????????)
????????????#?根據(jù)內(nèi)容自適應(yīng)大小
????????????self.talkLabel.adjustSize()
????????else:
????????????#?talk_condition為1顯示為別點我,這里同樣可以通過if-else-if來拓展對應(yīng)的行為
????????????self.talkLabel.setText("別點我")
????????????self.talkLabel.setStyleSheet(
????????????????"font:?bold;"
????????????????"font:25pt?'楷體';"
????????????????"color:white;"
????????????????"background-color:?white"
????????????????"url(:/)"
????????????)
????????????self.talkLabel.adjustSize()
????????????#?設(shè)置為正常狀態(tài)
????????????self.talk_condition?=?0
⑤ 實現(xiàn)能夠拖動寵物,通過多個自帶函數(shù)實現(xiàn),其代碼配置如下:
實現(xiàn)寵物的拖動主要通過三個函數(shù)實現(xiàn),mouserPressEvent負(fù)責(zé)在鼠標(biāo)點擊判斷其是否在寵物窗口上,如果在則將寵物和鼠標(biāo)的位置綁定,并執(zhí)行點擊改變寵物GIF圖和對話框的操作。
mouseMoveEvent實現(xiàn)按下后寵物跟著鼠標(biāo)移動
mouseReleaseEvent將之前的鎖定取消
?#?鼠標(biāo)左鍵按下時,?寵物將和鼠標(biāo)位置綁定
????def?mousePressEvent(self,?event):
????????#?更改寵物狀態(tài)為點擊
????????self.condition?=?1
????????#?更改寵物對話狀態(tài)
????????self.talk_condition?=?1
????????#?即可調(diào)用對話狀態(tài)改變
????????self.talk()
????????#?即刻加載寵物點擊動畫
????????self.randomAct()
????????if?event.button()?==?Qt.LeftButton:
????????????self.is_follow_mouse?=?True
????????#?globalPos()?事件觸發(fā)點相對于桌面的位置
????????#?pos()?程序相對于桌面左上角的位置,實際是窗口的左上角坐標(biāo)
????????self.mouse_drag_pos?=?event.globalPos()?-?self.pos()
????????event.accept()
????????#?拖動時鼠標(biāo)圖形的設(shè)置
????????self.setCursor(QCursor(Qt.OpenHandCursor))
?
????#?鼠標(biāo)移動時調(diào)用,實現(xiàn)寵物隨鼠標(biāo)移動
????def?mouseMoveEvent(self,?event):
????????#?如果鼠標(biāo)左鍵按下,且處于綁定狀態(tài)
????????if?Qt.LeftButton?and?self.is_follow_mouse:
????????????#?寵物隨鼠標(biāo)進行移動
????????????self.move(event.globalPos()?-?self.mouse_drag_pos)
????????event.accept()
?
????#?鼠標(biāo)釋放調(diào)用,取消綁定
????def?mouseReleaseEvent(self,?event):
????????self.is_follow_mouse?=?False
????????#?鼠標(biāo)圖形設(shè)置為箭頭
????????self.setCursor(QCursor(Qt.ArrowCursor))
⑥ 實現(xiàn)寵物右鍵點擊具有交互功能,通過函數(shù)contextMenuEvent實現(xiàn),其代碼配置如下:
退出操作通過 qApp.quit()實現(xiàn),直接退出相應(yīng)的QT程序。
隱藏操作則通過self.setWindowOpacity(0)實現(xiàn),這個可控制窗口的透明度。
?#?寵物右鍵點擊交互
????def?contextMenuEvent(self,?event):
????????#?定義菜單
????????menu?=?QMenu(self)
????????#?定義菜單項
????????quitAction?=?menu.addAction("退出")
????????hide?=?menu.addAction("隱藏")
????????#?使用exec_()方法顯示菜單。從鼠標(biāo)右鍵事件對象中獲得當(dāng)前坐標(biāo)。mapToGlobal()方法把當(dāng)前組件的相對坐標(biāo)轉(zhuǎn)換為窗口(window)的絕對坐標(biāo)。
????????action?=?menu.exec_(self.mapToGlobal(event.pos()))
????????#?點擊事件為退出
????????if?action?==?quitAction:
????????????qApp.quit()
????????#?點擊事件為隱藏
????????if?action?==?hide:
????????????#?通過設(shè)置透明度方式隱藏寵物
????????????self.setWindowOpacity(0)

⑦ 鼠標(biāo)移到寵物上的時候顯示為閉合的手
????#?鼠標(biāo)移進時調(diào)用
????def?enterEvent(self,?event):
????????#?設(shè)置鼠標(biāo)形狀?Qt.ClosedHandCursor???非指向手
????????self.setCursor(Qt.ClosedHandCursor)
2.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()
????????#?寵物靜態(tài)gif圖加載
????????self.initPetImage()
????????#?寵物正常待機,實現(xiàn)隨機切換動作
????????self.petNormalAction()
?
?
????#?窗體初始化
????def?init(self):
????????#?初始化
????????#?設(shè)置窗口屬性:窗口無標(biāo)題欄且固定在最前面
????????#?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()
?
????#?托盤化設(shè)置初始化
????def?initPall(self):
????????#?導(dǎo)入準(zhǔn)備在托盤化顯示上使用的圖標(biāo)
????????icons?=?os.path.join('tigerIcon.jpg')
????????#?設(shè)置右鍵顯示最小化的菜單項
????????#?菜單項退出,點擊后調(diào)用quit函數(shù)
????????quit_action?=?QAction('退出',?self,?triggered=self.quit)
????????#?設(shè)置這個點擊選項的圖片
????????quit_action.setIcon(QIcon(icons))
????????#?菜單項顯示,點擊后調(diào)用showing函數(shù)
????????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類為應(yīng)用程序在系統(tǒng)托盤中提供一個圖標(biāo)
????????self.tray_icon?=?QSystemTrayIcon(self)
????????#?設(shè)置托盤化圖標(biāo)
????????self.tray_icon.setIcon(QIcon(icons))
????????#?設(shè)置托盤化菜單項
????????self.tray_icon.setContextMenu(self.tray_icon_menu)
????????#?展示
????????self.tray_icon.show()
?
????#?寵物靜態(tài)gif圖加載
????def?initPetImage(self):
????????#?對話框定義
????????self.talkLabel?=?QLabel(self)
????????#?對話框樣式設(shè)計
????????self.talkLabel.setStyleSheet("font:15pt?'楷體';border-width:?1px;color:blue;")
????????#?定義顯示圖片部分
????????self.image?=?QLabel(self)
????????#?QMovie是一個可以存放動態(tài)視頻的類,一般是配合QLabel使用的,可以用來存放GIF動態(tài)圖
????????self.movie?=?QMovie("normal/normal1.gif")
????????#?設(shè)置標(biāo)簽大小
????????self.movie.setScaledSize(QSize(200,?200))
????????#?將Qmovie在定義的image中顯示
????????self.image.setMovie(self.movie)
????????self.movie.start()
????????self.resize(1024,?1024)
????????#?調(diào)用自定義的randomPosition,會使得寵物出現(xiàn)位置隨機
????????self.randomPosition()
????????#?展示
????????self.show()
????????#?https://new.qq.com/rain/a/20211014a002rs00
????????#?將寵物正常待機狀態(tài)的動圖放入pet1中
????????self.pet1?=?[]
????????for?i?in?os.listdir("normal"):
????????????self.pet1.append("normal/"?+?i)
????????#?將寵物正常待機狀態(tà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):
????????#?每隔一段時間做個動作
????????#?定時器設(shè)置
????????self.timer?=?QTimer()
????????#?時間到了自動執(zhí)行
????????self.timer.timeout.connect(self.randomAct)
????????#?動作時間切換設(shè)置
????????self.timer.start(3000)
????????#?寵物狀態(tài)設(shè)置為正常
????????self.condition?=?0
????????#?每隔一段時間切換對話
????????self.talkTimer?=?QTimer()
????????self.talkTimer.timeout.connect(self.talk)
????????self.talkTimer.start(3000)
????????#?對話狀態(tài)設(shè)置為常態(tài)
????????self.talk_condition?=?0
????????#?寵物對話框
????????self.talk()
?
????#?隨機動作切換
????def?randomAct(self):
????????#?condition記錄寵物狀態(tài),寵物狀態(tài)為0時,代表正常待機
????????if?not?self.condition:
????????????#?隨機選擇裝載在pet1里面的gif圖進行展示,實現(xiàn)隨機切換
????????????self.movie?=?QMovie(random.choice(self.pet1))
????????????#?寵物大小
????????????self.movie.setScaledSize(QSize(200,?200))
????????????#?將動畫添加到label中
????????????self.image.setMovie(self.movie)
????????????#?開始播放動畫
????????????self.movie.start()
????????#?condition不為0,轉(zhuǎn)為切換特有的動作,實現(xiàn)寵物的點擊反饋
????????#?這里可以通過else-if語句往下拓展做更多的交互功能
????????else:
????????????#?讀取特殊狀態(tài)圖片路徑
????????????self.movie?=?QMovie("./click/click.gif")
????????????#?寵物大小
????????????self.movie.setScaledSize(QSize(200,?200))
????????????#?將動畫添加到label中
????????????self.image.setMovie(self.movie)
????????????#?開始播放動畫
????????????self.movie.start()
????????????#?寵物狀態(tài)設(shè)置為正常待機
????????????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))
????????????#?設(shè)置樣式
????????????self.talkLabel.setStyleSheet(
????????????????"font:?bold;"
????????????????"font:25pt?'楷體';"
????????????????"color:white;"
????????????????"background-color:?white"
????????????????"url(:/)"
????????????)
????????????#?根據(jù)內(nèi)容自適應(yīng)大小
????????????self.talkLabel.adjustSize()
????????else:
????????????#?talk_condition為1顯示為別點我,這里同樣可以通過if-else-if來拓展對應(yīng)的行為
????????????self.talkLabel.setText("別點我")
????????????self.talkLabel.setStyleSheet(
????????????????"font:?bold;"
????????????????"font:25pt?'楷體';"
????????????????"color:white;"
????????????????"background-color:?white"
????????????????"url(:/)"
????????????)
????????????self.talkLabel.adjustSize()
????????????#?設(shè)置為正常狀態(tài)
????????????self.talk_condition?=?0
?
????#?退出操作,關(guān)閉程序
????def?quit(self):
????????self.close()
????????sys.exit()
?
????#?顯示寵物
????def?showwin(self):
????????#?setWindowOpacity()設(shè)置窗體的透明度,通過調(diào)整窗體透明度實現(xiàn)寵物的展示和隱藏
????????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)
?
????#?鼠標(biāo)左鍵按下時,?寵物將和鼠標(biāo)位置綁定
????def?mousePressEvent(self,?event):
????????#?更改寵物狀態(tài)為點擊
????????self.condition?=?1
????????#?更改寵物對話狀態(tài)
????????self.talk_condition?=?1
????????#?即可調(diào)用對話狀態(tài)改變
????????self.talk()
????????#?即刻加載寵物點擊動畫
????????self.randomAct()
????????if?event.button()?==?Qt.LeftButton:
????????????self.is_follow_mouse?=?True
????????#?globalPos()?事件觸發(fā)點相對于桌面的位置
????????#?pos()?程序相對于桌面左上角的位置,實際是窗口的左上角坐標(biāo)
????????self.mouse_drag_pos?=?event.globalPos()?-?self.pos()
????????event.accept()
????????#?拖動時鼠標(biāo)圖形的設(shè)置
????????self.setCursor(QCursor(Qt.OpenHandCursor))
?
????#?鼠標(biāo)移動時調(diào)用,實現(xiàn)寵物隨鼠標(biāo)移動
????def?mouseMoveEvent(self,?event):
????????#?如果鼠標(biāo)左鍵按下,且處于綁定狀態(tài)
????????if?Qt.LeftButton?and?self.is_follow_mouse:
????????????#?寵物隨鼠標(biāo)進行移動
????????????self.move(event.globalPos()?-?self.mouse_drag_pos)
????????event.accept()
?
????#?鼠標(biāo)釋放調(diào)用,取消綁定
????def?mouseReleaseEvent(self,?event):
????????self.is_follow_mouse?=?False
????????#?鼠標(biāo)圖形設(shè)置為箭頭
????????self.setCursor(QCursor(Qt.ArrowCursor))
?
?
????#?鼠標(biāo)移進時調(diào)用
????def?enterEvent(self,?event):
????????#?設(shè)置鼠標(biāo)形狀?Qt.ClosedHandCursor???非指向手
????????self.setCursor(Qt.ClosedHandCursor)
?
????#?寵物右鍵點擊交互
????def?contextMenuEvent(self,?event):
????????#?定義菜單
????????menu?=?QMenu(self)
????????#?定義菜單項
????????quitAction?=?menu.addAction("退出")
????????hide?=?menu.addAction("隱藏")
????????#?使用exec_()方法顯示菜單。從鼠標(biāo)右鍵事件對象中獲得當(dāng)前坐標(biāo)。mapToGlobal()方法把當(dāng)前組件的相對坐標(biāo)轉(zhuǎn)換為窗口(window)的絕對坐標(biāo)。
????????action?=?menu.exec_(self.mapToGlobal(event.pos()))
????????#?點擊事件為退出
????????if?action?==?quitAction:
????????????qApp.quit()
????????#?點擊事件為隱藏
????????if?action?==?hide:
????????????#?通過設(shè)置透明度方式隱藏寵物
????????????self.setWindowOpacity(0)
?
?
if?__name__?==?'__main__':
????#?創(chuàng)建了一個QApplication對象,對象名為app,帶兩個參數(shù)argc,argv
????#?所有的PyQt5應(yīng)用必須創(chuàng)建一個應(yīng)用(Application)對象。sys.argv參數(shù)是一個來自命令行的參數(shù)列表。
????app?=?QApplication(sys.argv)
????#?窗口組件初始化
????pet?=?DesktopPet()
????# 1. 進入時間循環(huán);
????# 2. wait,直到響應(yīng)app可能的輸入;
????# 3. QT接收和處理用戶及系統(tǒng)交代的事件(消息),并傳遞到各個窗口;
????# 4. 程序遇到exit()退出時,機會返回exec()的值。
????sys.exit(app.exec_())
三、程序打包
3.1 安裝pyinstaller
pip?install?pyinstaller?
如果提示黃色提示pip版本問題,照著上面的提示修改即可
3.2 項目目錄下完成打包
進入打開cmd命令行,進入項目目錄,輸入命令
pyinstaller?-F?-w?main.py

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

這里因為我自己的原因,需要將main.exe放到主目錄下才可正常運行

四、總結(jié)與參考資料
4.1 項目百度網(wǎng)盤:
鏈接:https://pan.baidu.com/s/1YYXzGpmCJkz43tYuki1wFQ 提取碼:3gkw

DeskTopPetEXE為帶打包好的文件。
DeskTopPet是打包前的文件。
4.2 總結(jié)
寫之前挺開心的,寫的時候也挺開心的,寫完之后就有點索然無味了。
長按或掃描下方二維碼,后臺回復(fù):加群,即可申請入群。一定要備注:來源+研究方向+學(xué)校/公司,否則不拉入群中,見諒!
(長按三秒,進入后臺)
推薦閱讀

