Textual MouseScrollRight 事件详解:捕获终端横向滚轮滚动
Textual MouseScrollRight 事件详解捕获终端横向滚轮滚动【免费下载链接】textualThe lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.项目地址: https://gitcode.com/gh_mirrors/te/textual导读MouseScrollRight是 Textual 事件体系中的一员专门用于响应鼠标滚轮或触控板手势在终端中向右滚动的事件。本文以 docs/events/mouse_scroll_right.md 为骨架深入 Textual 源码与测试完整讲解该事件的定义、触发时机、属性与方法、在 Widget 内的默认行为横向滚动以及如何编写自定义处理器实现专属交互逻辑。事件定义与继承关系MouseScrollRight定义于 src/textual/events.pyrich.repr.auto class MouseScrollRight(MouseEvent, bubbleTrue, verboseTrue): Sent when the mouse wheel is scrolled *right*. - [X] Bubbles - [X] Verbose 从源码可以看出该事件的两个关键特征Bubbles冒泡事件会从产生它的控件向父控件逐级冒泡父级可以统一监听或拦截通过调用event.stop()Verbose冗长日志与Click等非 Verbose 事件不同滚动事件属于高频事件Textual 会将其记录在冗长日志verbose log中方便调试滚动相关的交互问题但生产环境日志中不会默认输出这些高频噪声。它与同族的 MouseScrollUp、MouseScrollDown、MouseScrollLeft 一样都直接继承自MouseEvent见 src/textual/events.py本身不新增任何字段全部属性和方法均来自父类。注意原文档明确指出——完整的属性与方法列表见MouseEvent。因此理解MouseScrollRight的关键在于吃透MouseEvent提供的坐标系、修饰键与滚动增量等信息。MouseEvent 提供的属性与坐标系MouseScrollRight继承自MouseEvent定义于 src/textual/events.py事件携带以下核心信息坐标类属性属性类型含义x/yint鼠标所在的相对单元格坐标相对接收事件的控件pointer_x/pointer_yfloat鼠标所在的相对像素级浮点坐标screen_x/screen_yint鼠标所在的屏幕绝对坐标相对屏幕左上角pointer_screen_x/pointer_screen_yfloat屏幕绝对坐标的浮点版本offsetOffset(x, y)组合成的相对偏移量screen_offsetOffset(screen_x, screen_y)组合成的屏幕偏移量滚动增量类属性属性类型含义delta_xint自上次鼠标消息以来 x 方向的变化量delta_yint自上次鼠标消息以来 y 方向的变化量deltaOffset(delta_x, delta_y)组合成的增量偏移量修饰键与按钮属性类型含义shiftboolShift 键是否按下metaboolMeta 键是否按下ctrlboolCtrl 键是否按下buttonint被按下的按键索引styleStyle鼠标下方光标位置的 Rich Style实用方法get_content_offset(widget)返回鼠标在指定控件内容区内的偏移量若落在 padding 或 border 区域则返回Noneget_content_offset_capture(widget)即使鼠标不在内容区内也返回相对内容区左上角的偏移量_apply_offset(x, y)在事件坐标基础上平移生成新事件用于消息沿 DOM 树向下转发时校正坐标系。这些坐标均为单元格cell整数坐标因为终端渲染以字符单元为最小单位delta_x/delta_y由XTermParser依据上一次鼠标位置实时计算见下文触发链路。事件的产生链路从 ANSI 序列到 MouseScrollRightMouseScrollRight并非凭空产生而是由终端的 SGR 鼠标协议\x1b[...M/m序列解析而来。核心解析逻辑位于 src/textual/_xterm_parser.pyif buttons 64: event_class [ events.MouseScrollUp, events.MouseScrollDown, events.MouseScrollLeft, events.MouseScrollRight, ][buttons 3] button 0这段代码揭示了事件类型的分派规则SGR 序列中的按钮码与64做按位与若结果非零则说明这是滚动事件随后用buttons 3取低 2 位作为索引映射到四个滚动方向其中索引3即对应MouseScrollRight。解析器还会维护上一次的鼠标坐标last_x/last_y据此计算delta_x int(x) - int(self.last_x) delta_y int(y) - int(self.last_y)并提取修饰键状态bool(buttons 4), # shift bool(buttons 8), # meta bool(buttons 16), # ctrl测试用例印证仓库测试 tests/test_xterm_parser.py 对右侧滚动事件的解析做了参数化验证pytest.mark.parametrize( sequence, shift, meta, [ (\x1b[67;18;25M, False, False), (\x1b[71;18;25M, True, False), (\x1b[75;18;25M, False, True), ], ) def test_mouse_scroll_right(parser, sequence, shift, meta): events list(parser.feed(sequence)) assert len(events) 1 event events[0] assert isinstance(event, MouseScrollRight) assert event.x 17 assert event.y 24 assert event.shift is shift assert event.meta is meta可以看到序列\x1b[67;18;25M按钮码 67 64 3被正确解析为一个MouseScrollRight事件坐标为(17, 24)序列中坐标从 1 开始计数源码中减 1 转为 0 基坐标且不带修饰键按钮码 71、75 则分别验证了 Shift、Meta 键状态位的解析。Widget 中的默认行为驱动横向滚动Textual 的Widget基类为滚动事件提供了开箱即用的默认处理。在 src/textual/widget.py 中def _on_mouse_scroll_right(self, event: events.MouseScrollRight) - None: if self.allow_horizontal_scroll: if self._scroll_right_for_pointer(): event.stop() def _on_mouse_scroll_left(self, event: events.MouseScrollLeft) - None: if self.allow_horizontal_scroll: if self._scroll_left_for_pointer(): event.stop()这意味着当鼠标在支持水平滚动的控件allow_horizontal_scroll为真上向右滚动时Textual 会自动调用_scroll_right_for_pointer()执行滚动滚动成功返回True后调用event.stop()停止冒泡避免父级重复处理因此如果你的控件本身具备水平滚动能力如设置了overflow-x: auto无需编写任何代码即可获得横向滚轮支持。如何监听与自定义处理由于事件具有冒泡特性你可以用两种方式捕获MouseScrollRight。方式一命名约定法按照 Textual 的命名约定为事件添加on_前缀、将类名转为蛇形命名即可自动关联处理器from textual.app import App, ComposeResult from textual.widgets import Static class ScrollWatcher(Static): def on_mouse_scroll_right(self, event: events.MouseScrollRight) - None: # 事件默认已由基类用于横向滚动若想自定义可在此覆盖 self.log(fScrolled right at ({event.screen_x}, {event.screen_y})) event.stop() # 停止冒泡方式二on装饰器法Textual 的 [on][textual.on] 装饰器用法见 docs/guide/events.md允许为事件绑定任意命名的方法且可配合 CSS 选择器精确指定要监听的控件from textual import on from textual.events import MouseScrollRight class MyApp(App): on(MouseScrollRight, #content) def handle_scroll(self, event: MouseScrollRight) - None: self.notify(fRight scroll at x{event.delta_x})提示on装饰器要求消息类具备control属性MouseEvent的control属性即返回鼠标下的控件见 src/textual/events.py因此可用于选择器匹配。与 Shift/Ctrl 组合Textual 的默认行为中垂直滚轮配合shift/ctrl也会被转换为横向滚动见 src/textual/widget.py 中_on_mouse_scroll_down/_on_mouse_scroll_up的event.ctrl or event.shift分支。因此在实际终端中即使硬件没有横向滚轮也可以用「Shift 垂直滚轮」触发等价的横向滚动效果。调试与日志由于MouseScrollRight标记为verboseTrue当你在终端按CtrlE打开 Textual Devtools 的日志或将日志级别调至 verbose 时滚动事件会以类似以下形式输出来自__rich_repr__见 src/textual/events.pyMouseScrollRight(None, x17, y24, delta_x0, delta_y0, button0, shiftFalse, metaFalse, ctrlFalse)其中各字段只有在非默认值时才会展示便于快速定位坐标与修饰键状态。与其他鼠标事件的协同MouseScrollRight通常与以下事件配合使用构成完整的鼠标交互体系MouseScrollLeft向左滚动MouseScrollUp / MouseScrollDown垂直方向滚动Click、MouseDown、MouseUp点击类交互MouseMove指针移动Enter / Leave鼠标进入/离开控件区域。设计自定义滚动控件如横向走马灯、图表横轴缩放、水平菜单切换时可在处理器中读取event.delta_x作为步进量或读取event.x/event.y判断滚动位置实现精细的分步控制。小结MouseScrollRight继承自MouseEvent具有冒泡与冗长日志特性本身不新增字段它的产生源于XTermParser对 SGR 鼠标协议序列的解析按钮码 64判定滚动、 3判定方向3为右Widget基类默认将其映射为水平右向滚动可零代码使用自定义处理可使用命名约定或on装饰器注意通过event.stop()控制冒泡。相关源码与测试索引事件类定义src/textual/events.py父类MouseEventsrc/textual/events.pyANSI 序列解析src/textual/_xterm_parser.py默认滚动行为src/textual/widget.py解析测试tests/test_xterm_parser.py事件处理指南docs/guide/events.md【免费下载链接】textualThe lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.项目地址: https://gitcode.com/gh_mirrors/te/textual创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →