通过启用终端的 X11/UTF-8 鼠标协议(如 \x1b[?1006h),配合实时读取 sys.stdin 的 CSI 序列,Python 程序可捕获鼠标移动事件并解析坐标;Textual 等库在此基础上结合渲染布局树实现精准悬停检测。
通过启用终端的 x11/utf-8 鼠标协议(如 `\x1b[?1006h`),配合实时读取 `sys.stdin` 的 csi 序列,python 程序可捕获鼠标移动事件并解析坐标;textual 等库在此基础上结合渲染布局树实现精准悬停检测。
在现代终端(如 kitty、alacritty、gnome-terminal ≥3.38、Windows Terminal)中,可通过 ANSI 转义序列启用鼠标事件报告模式,使终端将鼠标移动、按下、释放等动作以特殊 CSI(Control Sequence Introducer)序列形式写入标准输入(stdin)。这并非“黑箱 hack”,而是遵循 DEC Private Mode (DECSET) 和 Xterm Mouse Protocol 标准的规范行为。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
✅ 正确启用鼠标跟踪的 ANSI 序列
你尝试的 \x1b[?1h\x1b[?9h... 混合了多种不兼容或已废弃的模式(如 ?1h 是启用 cursor keys mode,?9h 是启用 X10 鼠标协议——早已被弃用)。推荐使用 UTF-8 编码的 SGR 模式(?1006h),它支持精确坐标、按钮状态和 Unicode 安全:
import sys
import tty
import termios
import select
# 启用 UTF-8 鼠标协议(推荐)
sys.stdout.write("\x1b[?1006h")
sys.stdout.flush()
# 设置 stdin 为非阻塞、无缓冲、原始模式
old_settings = termios.tcgetattr(sys.stdin)
try:
tty.setraw(sys.stdin.fileno())
print("✅ 鼠标跟踪已启用。移动鼠标,按 Ctrl+C 退出。")
while True:
# 检查是否有输入(避免阻塞)
if select.select([sys.stdin], [], [], 0.1)[0]:
data = sys.stdin.read(1)
if data == "\x1b": # ESC 后可能跟 CSI 序列
# 尝试读取后续字符(典型鼠标序列:ESC [ M Cb Cx Cy)
# 注意:UTF-8 模式下为 ESC [ = 3:
try:
button_code = int(parts[0])
x = int(parts[1]) - 1 # 终端坐标从 1 开始
y = int(parts[2]) - 1
print(f"?️ 鼠标位置:({x}, {y}),按钮码:{button_code}")
except ValueError:
pass
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
# ⚠️ 必须关闭协议,否则终端可能残留异常行为
sys.stdout.write("\x1b[?1006l")
sys.stdout.flush()
? 关键说明与注意事项
- 协议选择优先级:?1006h(UTF-8 SGR) > ?1015h(urxvt 扩展) > ?1005h(UTF-8 基础) > ?1000h(X10,仅支持左键+坐标,不推荐)。
- 坐标系:终端以左上角为 (1,1),x 为列号,y 为行号;实际应用中需减 1 转换为 0-based 索引。
- 布局映射是核心:单纯获取坐标并无意义——Textual 的真正能力在于其内部维护的渲染布局树(render tree)。它记录每个 Widget 在虚拟屏幕上的精确矩形区域(Region),收到 (x, y) 后通过 O(1) 区域命中检测(如 region.contains(x, y))快速定位目标控件。
- 安全退出:务必用 \x1b[?1006l 关闭协议,否则可能导致终端鼠标行为异常(如光标消失、粘滞)。
- 平台限制:Windows CMD 不支持;PowerShell 7+ / Windows Terminal 支持良好;macOS Terminal.app 默认不支持,推荐使用 iTerm2 或 Kitty。
✅ 总结
获取鼠标悬停位置 ≠ 直接“读取像素坐标”,而是一套协同机制:
① 终端层:通过标准 ANSI 协议上报事件;
② 输入层:程序以 raw 模式解析 CSI 序列;
③ 应用层:结合自身 UI 布局信息完成语义化映射。
Textual 并未使用“hack”,而是严谨实现了终端协议 + 布局引擎的完整链路——这也是构建响应式终端 GUI 的专业路径。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










