如何用Pygame构建时间线UI:Memento前端界面实现深度解析
【免费下载链接】MementoMemento is a Python app that records everything you do on your computer and lets you go back in time, search, and chat with a LLM (Large Language Model) to find back information about what you did.项目地址: https://gitcode.com/gh_mirrors/mem/Memento
想不想打造一个能"倒回时间"的桌面应用界面?Memento 就是这样一个开源项目:它每两秒截取一次屏幕,通过 OCR 提取文字并建立索引,最终用Pygame 构建时间线UI让用户可以像翻看历史录像一样回溯电脑上的所有操作。本文将以 Memento 前端界面为案例,深入解析如何用 Pygame 构建时间线UI,从主循环设计、时间条组件到 AI 聊天面板,带你拆解一个真实可运行的 Pygame 桌面应用。
为什么用 Pygame 构建时间线UI?🧐
Memento 选择 Pygame 而非 Qt/Electron 的核心原因在于实时渲染能力:时间线UI 需要流畅滚动、缩放、悬停预览视频帧,Pygame 的 Surface 和 blit 机制天然适合高频图像刷新。同时,Python 生态让 Memento 可以直接复用 OpenCV(图像处理)、Tesseract(OCR)、LangChain(大模型问答)等库,无需跨语言桥接。
整体架构:一条主循环撑起整个前端
Memento 的前端入口是 timeline.py 中的Timeline类。它只做了两件"小事",却撑起了整个界面:
1. 初始化窗口:自适应屏幕分辨率
代码先通过pygame.display.Info()获取屏幕分辨率,并把窗口设置为屏幕的约 95% 大小,配合SRCALPHA + NOFRAME标志实现无边框透明渲染,让"时间回放"界面像系统覆盖层一样自然:
self.window_size = (int(infoObject.current_w / 1.05), int(infoObject.current_h / 1.05)) self.screen = pygame.display.set_mode(self.window_size, flags=pygame.SRCALPHA + pygame.NOFRAME)注意它用pygame.display.init()+pygame.font.init()替代全量pygame.init(),启动更快,这是值得借鉴的性能细节。
2. 主循环:Draw → Input → Update 三段式
run()方法揭示了 Pygame 时间线UI 的标准骨架:先填充黑底,依次绘制当前帧、时间条、搜索栏、聊天面板,然后处理输入事件,最后刷新 FPS 统计并pygame.display.update()。每个组件都是一个独立对象,只暴露draw(screen, ...)和events(...)两个方法,模块间解耦非常干净。
时间条组件:时间线UI的核心亮点 ⏱️
time_bar.py 是整个前端最有设计感的部分。它把"时间线"变成一条按应用着色的分段彩条:
- 应用分段:后台遍历每一帧的
window_title元数据,把同一应用的连续帧合并成一个色段,每个应用从 16 色调色板取色,超出后随机生成(见 apps.py)。 - 图标识别:通过 icon_getter.py 扫描系统
/usr/share/icons目录,用模糊匹配(fuzz.ratio)找到对应应用图标,悬停时放大显示,非常直观。 - 游标与缩放:白色竖线标记当前位置,
Ctrl+滚轮缩放时间窗口(tws),缩放时动态重算可视区间,并在接近边界时自动滚动偏移,保证游标不丢失。 - 悬停预览:鼠标悬停时间条任意位置时,会按 0.2 倍缩放渲染对应帧的截图预览,并显示"Today 14:32"这类友好时间(今天/昨天/前天自动转换)。
帧渲染与缓存:流畅回放的关键 🎞️
时间线UI 要回放海量历史帧,直接读取视频必然卡顿。frame_getter.py 的解决思路是两级缓存:
- 视频帧通过
ReadersCache缓存,同一帧只解码一次; - 当前显示帧单独保存,
get_frame()在帧号未变时直接返回缓存,避免重复的 resize 和颜色转换。
它还负责把搜索结果以红色半透明高亮框 + 文字标注的形式叠加到帧上,并显示"X results"计数,让用户一眼看到命中位置。
搜索功能:Ctrl+F 全量检索历史 📝
search_bar.py 实现了类似 IDE 的搜索体验:按下Ctrl+F弹出左侧搜索面板,输入关键词后通过 db.py 的 SQLiteFTS5 全文索引查询,结果以列表形式呈现,点击任意条目即可跳转到对应时间点,当前帧对应条目会以红色边框高亮。
AI 聊天侧栏:让时间线开口说话 🤖
Memento 最惊艳的功能是 chat.py 实现的 AI 聊天面板(Ctrl+T唤起):
- 使用 LangChain 的
ConversationalRetrievalChain+ Chroma 向量数据库,对 OCR 文本做语义检索; - 查询在独立多进程中进行,UI 不卡顿,回答以 JSON 返回(包含
answer和frames_ids); - 聊天气泡左侧是问题(绿色)、右侧是回答(蓝色),回答中引用的历史帧会以缩略图形式嵌入气泡下方,点击缩略图即可跳转回那一刻——真正实现了"问 AI 就能找回记忆"。
区域OCR:框选即提取文字 ✂️
region_selector.py 允许用户在任意历史帧上拖拽框选区域,调用 Tesseract OCR 识别框内文字并生成带坐标的标注,Ctrl+C即可复制全文。配合 ui.py 的PopUpManager淡出提示(如"Text copied to clipboard"),交互反馈非常完整。
调试利器:内建 FPS 监控与红色录制灯 🔴
开发调试时,按下D键可进入 Debug 模式:ui.py 中的Plot类实时绘制 FPS 折线图,同时右上角显示帧号。录制状态则以闪烁的红点提示——通过检查memento-bg进程是否存在来判断是否正在记录。
小结:从 Memento 学到的 4 个 Pygame UI 设计要点
- 组件化:每个 UI 元素独立成类,只暴露
draw和events接口,主循环保持清爽; - 缓存优先:帧读取、图标匹配都做缓存,这是时间线UI 流畅体验的基石;
- 善用元数据:时间条着色、图标展示、时间提示全部来自录制时的窗口元数据,UI 只做消费;
- 进程隔离:AI 查询放到子进程,避免阻塞渲染主循环。
如果你也想用 Pygame 构建时间线UI 或类似的桌面应用,直接参考 Memento 的 timeline 目录 就能找到所有答案。克隆仓库后运行memento-timeline命令,即可亲自体验这个"记忆回放器"的完整前端界面!
【免费下载链接】MementoMemento is a Python app that records everything you do on your computer and lets you go back in time, search, and chat with a LLM (Large Language Model) to find back information about what you did.项目地址: https://gitcode.com/gh_mirrors/mem/Memento
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考