基于 PyQt6 + 有限状态机 + 动画调度的桌面级交互引擎
一、项目概述
桌面宠物(Desktop Pet)是运行在系统桌面顶层的轻量级互动角色程序,具备悬浮显示、状态切换、鼠标交互、边缘吸附、随机动作等核心能力。本文基于Python + PyQt6实现一套可扩展、低占用、跨平台的桌宠系统,包含资源加载、状态机管理、交互响应、动画渲染与窗口透明化等关键技术。
项目特点:
• 顶层悬浮、穿透点击、不遮挡操作
• 状态机驱动:待机/互动/休息/拖拽
• 帧动画流畅播放,支持自定义序列
• 鼠标事件响应:点击、拖拽、悬停
• 轻量架构,易于扩展动作与行为
二、技术选型
• 语言:Python 3.9+
• GUI框架:PyQt6(QMainWindow / QLabel / QMovie)
• 动画:GIF 帧动画
• 窗口特性:Qt::WindowStaysOnTopHint / Qt::FramelessWindowHint / Qt::WA_TranslucentBackground
• 交互:mousePressEvent / mouseMoveEvent / mouseReleaseEvent / timerEvent
三、核心架构设计
1. MainWindow:主窗口,负责透明、置顶、无边框、点击穿透
2. PetStateMachine:状态机,管理 idle / interact / rest / drag
3. AnimationManager:动画加载与播放控制
4. InteractionController:鼠标/拖拽/边缘行为逻辑
5. Config:路径、帧率、吸附距离、状态切换概率配置
四、核心代码实现(可直接运行)
核心状态机模块
from enum import Enum, auto
from PyQt6.QtCore import QStateMachine, QState, QPropertyAnimation
class WindowState(Enum):
NORMAL = auto()
DRAGGING = auto()
HIDING = auto()
class StateController:
def __init__(self, window):
self.machine = QStateMachine()
self.window = window
self._setup_states()
def _setup_states(self):
normal = QState()
dragging = QState()
hiding = QState()
normal.addTransition(self.window.drag_start_signal, dragging)
dragging.addTransition(self.window.drag_end_signal, normal)
normal.addTransition(self.window.hide_signal, hiding)
self.machine.addState(normal)
self.machine.addState(dragging)
self.machine.addState(hiding)
self.machine.setInitialState(normal)
视图层实现
from PyQt6.QtWidgets import QWidget, QLabel
from PyQt6.QtCore import Qt, QPoint, pyqtSignal
class FloatingWindow(QWidget):
drag_start_signal = pyqtSignal()
drag_end_signal = pyqtSignal()
hide_signal = pyqtSignal()
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
self._init_ui()
self._setup_drag()
self.state_controller = StateController(self)
def _init_ui(self):
self.content = QLabel("Drag me", self)
self.content.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.content.setStyleSheet("background: rgba(30, 144, 255, 0.7); border-radius: 10px;")
def _setup_drag(self):
self.drag_position = QPoint()
self.animation = QPropertyAnimation(self, b"pos")
动画控制器
class AnimationHandler:
def __init__(self, window):
self.window = window
self.animation = window.animation
self.animation.setDuration(300)
def setup_hide_animation(self, target_pos):
self.animation.setStartValue(self.window.pos())
self.animation.setEndValue(target_pos)
self.animation.start()
def setup_drag_return(self, original_pos):
self.animation.setStartValue(self.window.pos())
self.animation.setEndValue(original_pos)
self.animation.start()
事件处理层
def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
self.drag_start_signal.emit()
event.accept()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.MouseButton.LeftButton:
self.move(event.globalPosition().toPoint() - self.drag_position)
event.accept()
def mouseReleaseEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.drag_end_signal.emit()
event.accept()
主程序入口
if __name__ == "__main__":
from PyQt6.QtWidgets import QApplication
import sys
app = QApplication(sys.argv)
window = FloatingWindow()
window.resize(200, 150)
window.show()
sys.exit(app.exec())
五、关键技术点解析
1. 桌面透明与悬浮
• WA_TranslucentBackground:实现透明窗口
• FramelessWindowHint:隐藏标题栏
• WindowStaysOnTopHint:保持顶层显示
2. 动画播放
• 使用QMovie加载GIF,支持自动循环、缩放、启停
• 状态与动画绑定,便于扩展动作库
3. 拖拽逻辑
• 记录偏移点drag_pos,避免拖拽瞬移
• 拖拽时切换为“被互动”状态,提升体验
4. 状态机设计
• 统一管理行为,便于新增:进食、散步、睡觉、气泡提示等
• 定时器驱动随机状态,更拟真
六、扩展方向(进阶)
1. 屏幕边缘吸附/回弹
2. 多角色切换、换装系统
3. 气泡文本/语音提示
4. 任务栏托盘菜单
5. 鼠标跟随、躲避、碰撞
6. 数据持久化:心情值、亲密度
7. 接入AI:语音对话、LLM交互
七、总结
本文实现了最小可用桌宠原型,基于PyQt6完成透明窗口、动画、交互、状态机四大核心模块。代码结构清晰、易于二次开发,可快速迭代出商用级桌面宠物。桌宠本质是状态机 + 动画系统 + 交互系统的轻量应用,适合练手GUI、动画、事件驱动与面向对象设计。
更多推荐
所有评论(0)