桌面寵物 ① 透過python製作屬於自己的桌面寵物

專注的阿熊發表於2022-05-13

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_())


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2894034/,如需轉載,請註明出處,否則將追究法律責任。

相關文章