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: 新窗口部件是一个子窗口,而无论窗口部件是否有父窗口部件 |
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() |
# 将宠物正常待机状态的动图放入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 ): |
# 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) |
# 鼠标左键按下时, 宠物将和鼠标位置绑定 |
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_()) |
初级程序员
by: 010101 发表于:2022-06-01 08:47:29 顶(0) | 踩(0) 回复
回复评论