引言

你有没有想过,让桌面上多一个会动、会弹、还会陪你聊天的小家伙?

BounceChat 就是这样一个项目。它不是一个趴在屏幕角落的静态桌宠,而是一个遵循物理规律、能识别你的窗口、还能用AI陪你聊天的桌面小伙伴。你把它扔出去,它真的会滚;你把它砸向浏览器窗口,它真的会弹开;你点击它,它会弹出气泡和你说话。

本专栏将带你从0到1,亲手实现这个有趣的项目。无论你是想学习PyQt5实战、对Windows API好奇,还是想把大模型塞进桌面应用,这里都有你要的答案。

在这里插入图片描述


📂 项目开源地址

整个项目的代码完全开源,放在 Gitee 上:

👉 Gitee BounceChat 雪豹同志

你可以:

  • Star 一下,养个桌面小伙伴
  • 📥 Clone 到本地,边看专栏边跑代码
  • 🐛 提Issue,发现bug或有好点子
  • 🔧 提交PR,一起让它变得更好

🎯 在这个专栏,你可以学到什么?

一、物理引擎:让小球真的会“撞”

这不是简单的“撞墙就反弹”动画,而是一套完整的物理模拟系统。你会学到:

1. 核心物理量的代码实现

  • 重力加速度:怎么调出让小球自然下落的参数
  • 摩擦力(空气阻力):为什么小球滚着滚着会自己停下
  • 反弹系数:碰撞时损失多少能量才像真的
  • 地面停留机制:速度慢到多少时小球会停住不动

2. 运动状态管理

  • 位置和速度的实时更新
  • 选中状态、拖动状态、吸附状态的切换逻辑
  • 帧同步(60fps)的物理更新循环

3. 视觉效果增强

  • 尾巴轨迹:用位置历史数组画出渐隐的拖尾
  • 选中发光:QRadialGradient实现的光晕效果
  • 参数调优:怎么调出“手感好”的弹跳效果

在这里插入图片描述

二、窗口识别:让小球“看见”你的屏幕

这是项目最独特的地方——小球能识别你打开了哪些窗口,并真的和它们发生碰撞。

1. Windows API 实战

  • ctypes 调用 user32.dll 的底层函数
  • EnumWindows 枚举所有顶级窗口
  • IsWindowVisible 过滤不可见窗口
  • IsIconic 排除最小化窗口
  • GetWindowRect 获取窗口精确位置
  • 用回调函数处理每个找到的窗口

2. 碰撞检测算法

  • 判断小球是否与窗口边缘相交
  • 区分上边缘碰撞和下边缘碰撞
  • 碰撞后的位置修正(防止嵌进窗口)
  • 根据速度决定是反弹还是停留
  • 实时更新:窗口移动时碰撞区域也跟着变

3. 性能优化

  • 窗口列表的缓存和更新频率控制
  • 只检测尺寸>100x100的有效窗口
  • 排除系统窗口(任务栏、Program Manager等)

在这里插入图片描述

三、AI对话:让小球真的会聊天

接入大模型后,小球不再只是个玩具,而是一个能陪你聊天的伙伴。

1. API集成

  • OpenAI SDK 的封装和使用
  • 模力方舟 DeepSeek-V3 的接入配置
  • 环境变量管理 API Key(安全第一)
  • 错误处理和重试机制

2. 对话管理

  • 用 JSON 文件持久化保存聊天历史
  • 系统角色设定:“你是一个运行在用户电脑桌面上的弹跳小球”
  • 回复长度限制(≤20字)的实现
  • 上下文保持:让小球记得之前聊过什么

3. 角色性格设计

  • 20字限制背后的思考:不啰嗦、刚刚好
  • 回复风格示例:“今天很开心!”“我是弹跳小球!”
  • 如何让回复既有AI能力又不失可爱

在这里插入图片描述

四、UI交互:PyQt5 + HTML/CSS/JS 混编

小球的“脸面”——聊天气泡,是用 HTML/CSS/JS 写的,然后嵌入到 PyQt5 里。

1. PyQt5 + WebEngineView 混编

  • 为什么用 WebEngineView 而不是纯 Qt 绘制
  • 加载本地 HTML 文件
  • 设置透明背景
  • 控制窗口标志(置顶、无边框)

2. Python 与 JavaScript 双向通信

  • QWebChannel 的原理和使用
  • 注册 Python 对象给 JS 调用
  • JS 调用 Python 方法(点击气泡关闭)
  • Python 接收 JS 传来的事件并处理

3. 位置同步

  • 气泡如何始终显示在小球上方
  • 边界检测:不让气泡跑出屏幕

五、交互控制:鼠标拖拽和键盘操控

小球怎么玩才顺手?全靠事件系统的精细调校。

1. 鼠标事件

  • mousePressEvent:判断是否点中了小球
  • mouseMoveEvent:拖动时更新小球位置,记录速度
  • mouseReleaseEvent:松开时根据拖动速度赋予初速度
  • 拖拽偏移量的计算

2. 键盘事件

  • 方向键给小球施加推力
  • 选中状态和未选中状态的区别处理
  • 边缘吸附后的“挣脱”逻辑

3. 状态机设计

  • 是否被选中(is_selected)
  • 是否正在拖动(is_dragging)
  • 是否吸附在边缘(is_stuck)
  • 是否停留在地面(on_ground)
  • 这些状态怎么协同工作

六、系统适配:高分屏和性能调优

让你的小球在所有电脑上都表现良好。

1. DPI 缩放适配

  • 用 Windows API 获取系统 DPI
  • 计算缩放因子(scale_factor)
  • 按比例调整窗口大小
  • WebView 的缩放设置

2. 性能优化

  • 物理更新频率(60fps 还是 30fps)
  • 窗口检测频率(100ms 还是 200ms)
  • 尾巴长度对性能的影响
  • 减少不必要的重绘

3. 常见问题解决

  • 小球卡在窗口后面怎么办
  • 气泡不显示排查步骤
  • API 调用失败的处理

🧠 思维难点深度拆解

这个项目最烧脑的地方,我单独拎出来讲透:

难点一:物理真实感的手感调校

问题:参数差一点,手感就全变。重力太大像铅球,太小像气球;摩擦力太大像刹车,太小像冰面。

解法

  • 用可配置参数(放到 config.json)
  • 边调边试,记录“手感好”的参数组合
  • 增加调试输出,实时看速度变化
  • 参考真实物理公式(但不用完全精确,好看更重要)

难点二:窗口碰撞的实时性和准确性

问题:窗口会动,小球也会动,每帧都要判断是否碰撞,还要区分撞的是哪条边。

解法

  • 每帧遍历窗口列表(优化后约20-30个窗口)
  • 用 AABB 碰撞检测(轴对齐包围盒)
  • 先判断水平范围,再判断垂直范围
  • 根据小球中心位置和速度方向决定反弹方向
  • 位置修正防止嵌窗

难点三:Python 调用 Windows API 的坑

问题:ctypes 用起来麻烦,要处理指针、回调、结构体,稍不注意就内存错误。

解法

  • 定义好函数原型(argtypes, restype)
  • 回调函数用 WINFUNCTYPE 包装
  • 结构体用 wintypes 里定义好的
  • 加上异常处理,捕获 Windows 错误
  • 多看微软官方文档和 ctypes 示例

难点四:WebChannel 的双向通信

问题:PyQt 的 WebEngineView 和 HTML 页面怎么传数据?文档少,网上示例也少。

解法

  • 先理解 QWebChannel 原理(注册对象、信号槽)
  • Python 端定义 QObject 子类,加 @pyqtSlot 方法
  • JS 端先加载 qwebchannel.js,再初始化
  • 通信成功后,先发个测试消息确认
  • pyqtSignal 实现 Python 主动给 JS 发消息

难点五:系统缩放导致的错位

问题:在 4K 屏上,小球可能变得极小,气泡位置错乱。

解法

  • 启动时获取系统 DPI
  • 所有固定尺寸都乘以缩放因子
  • 气泡位置按小球位置计算时也考虑缩放
  • WebView 设置 setZoomFactor
  • 测试不同分辨率(至少 100%、125%、150%、200%)

🛠️ 完整技术栈

领域 技术 作用
编程语言 Python 3.7+ 主逻辑开发
GUI框架 PyQt5 窗口管理、绘图、事件处理
Web渲染 PyQtWebEngine 显示HTML气泡
前后端通信 QWebChannel Python与JavaScript互调
窗口API Windows API (ctypes) 枚举窗口、获取位置
AI对话 OpenAI SDK + 模力方舟API 接入大模型(DeepSeek-V3)
前端UI HTML5/CSS3/JavaScript 气泡样式与交互
数据存储 JSON 保存对话历史
配置管理 python-dotenv(可选) 管理 API Key
系统调用 ctypes.wintypes Windows 数据结构

🎯 适合谁看?

这个专栏不是写给“所有人”的,而是写给下面这几类人:

人群 能获得什么
PyQt5 初学者 一个完整实战项目,比看一百遍教程都管用
Windows API 好奇者 Python 调用底层 API 的完整示例
AI 应用开发者 大模型和桌面应用结合的最佳实践
桌面应用爱好者 看看别人怎么把想法变成代码
单纯觉得好玩的人 代码在这,跑起来就能收获快乐

不需要你已经是 PyQt5 高手,也不需要你写过 Windows API。我会从最基础的地方讲起,每一步都有代码、有解释、有踩坑记录。


💡 为什么值得花时间看?

市面上有很多 PyQt5 教程,但大多是“写个计算器”“写个记事本”。那些项目当然能学到东西,但总觉得差点意思。

BounceChat 不一样:

  1. 它真的有趣——当你第一次看到小球在桌面上弹起来,第一次听到它回复你“今天很开心”,那种成就感是写计算器给不了的。

  2. 它足够复杂——物理模拟、窗口交互、AI 对话、Web 混编,每个模块拿出来都能单独写一篇。学完这个,PyQt5 的大部分功能你都摸过了。

  3. 它踩过的坑我都替你踩了——Windows API 怎么调、WebChannel 怎么通、缩放怎么适配,每个坑都有解决方案,你不用再走一遍。

  4. 代码完全开源——不是“讲一半留一半”,整个项目都在那里,你可以边看边跑,甚至可以提 PR 一起完善。


最后

你的桌面,是不是缺一个会弹跳的小伙伴?

跟着这个专栏,从0到1,把它请到你电脑上。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐