Textual OptionList 组件完全指南:可导航选项列表的构建与交互
Textual OptionList 组件完全指南可导航选项列表的构建与交互【免费下载链接】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本文面向使用 Python 终端 UI 框架 Textual 的开发者系统讲解OptionList组件的完整用法从最基础的字符串选项列表、带 ID 与禁用状态的Option实例到以任意 Rich renderable如表格作为选项条目的高级用法并深入解析其响应式属性、事件消息、按键绑定、组件类与常用 API同时结合仓库源码与测试用例说明底层实现原理。读完本文你将能独立构建一个可键盘导航、可鼠标点选、可动态增删改的垂直选项列表。OptionList是 Textual 在0.17.0版本引入的组件用于展示一个垂直排列的、可导航的选项列表。它属于可聚焦Focusable组件文档标记为[x] Focusable但不是容器Container——它继承自ScrollView见 源码专门用于单选场景例如菜单、命令选择、列表选择等。与同为列表类组件的ListView相比OptionList的显著特点是每个选项的提示内容prompt可以是任意 Rich renderableRich 渲染对象因此选项的高度可以任意——这为构建富文本菜单提供了极大的灵活性。三种构建选项的方式1. 简单字符串选项构造OptionList时最简单的做法是直接传入一串字符串每个字符串会自动成为一个选项from textual.app import App, ComposeResult from textual.widgets import Footer, Header, OptionList class OptionListApp(App[None]): CSS_PATH option_list.tcss def compose(self) - ComposeResult: yield Header() yield OptionList( Aerilon, Aquaria, Canceron, Caprica, Gemenon, Leonis, Libran, Picon, Sagittaron, Scorpia, Tauron, Virgon, ) yield Footer() if __name__ __main__: OptionListApp().run()完整示例见 docs/examples/widgets/option_list_strings.py。对应的样式文件 option_list.tcss 将选项列表居中放置Screen { align: center middle; } OptionList { width: 70%; height: 80%; }2. 使用Option实例与分隔线当需要更精细的控制——例如为选项设置 ID、设置初始禁用状态——应使用Option类。此外在选项序列中插入None即可在前后选项之间绘制一条分隔线from textual.app import App, ComposeResult from textual.widgets import Footer, Header, OptionList from textual.widgets.option_list import Option class OptionListApp(App[None]): CSS_PATH option_list.tcss def compose(self) - ComposeResult: yield Header() yield OptionList( Option(Aerilon, idaer), Option(Aquaria, idaqu), None, Option(Canceron, idcan), Option(Caprica, idcap, disabledTrue), None, Option(Gemenon, idgem), None, Option(Leonis, idleo), Option(Libran, idlib), None, Option(Picon, idpic), None, Option(Sagittaron, idsag), Option(Scorpia, idsco), None, Option(Tauron, idtau), None, Option(Virgon, idvir), ) yield Footer() if __name__ __main__: OptionListApp().run()完整示例见 docs/examples/widgets/option_list_options.py。Option的构造签名见 源码为Option(prompt: VisualType, id: str | None None, disabled: bool False)参数类型默认值说明promptVisualType必填选项显示的提示内容文本或 Rich renderableidstr \| NoneNone选项的 ID用于之后通过 ID 查询、修改、删除选项disabledboolFalse是否禁用该选项。被禁用的选项会以灰色显示且不可被选中、不可被导航高亮注意ID 在同一列表中必须唯一。若尝试添加重复 ID 的选项会抛出DuplicateID异常见 源码 与测试 tests/option_list/test_option_list_create.py。ID 在OptionList挂载后即可通过get_option查询回归测试见test_options_are_available_soon对应 issue #3903。3. 以 Rich renderable 作为选项由于Option的prompt可以是任意 Rich renderable选项的高度可以任意。下面的例子用 Rich 的Table作为每个选项的内容每个选项都是一个独立的表格from __future__ import annotations from rich.table import Table from textual.app import App, ComposeResult from textual.widgets import Footer, Header, OptionList COLONIES: tuple[tuple[str, str, str, str], ...] ( (Aerilon, Demeter, 1.2 Billion, Gaoth), (Aquaria, Hermes, 75,000, None), (Canceron, Hephaestus, 6.7 Billion, Hades), (Caprica, Apollo, 4.9 Billion, Caprica City), (Gemenon, Hera, 2.8 Billion, Oranu), (Leonis, Artemis, 2.6 Billion, Luminere), (Libran, Athena, 2.1 Billion, None), (Picon, Poseidon, 1.4 Billion, Queenstown), (Sagittaron, Zeus, 1.7 Billion, Tawa), (Scorpia, Dionysus, 450 Million, Celeste), (Tauron, Ares, 2.5 Billion, Hypatia), (Virgon, Hestia, 4.3 Billion, Boskirk), ) class OptionListApp(App[None]): CSS_PATH option_list.tcss staticmethod def colony(name: str, god: str, population: str, capital: str) - Table: table Table(titlefData for {name}, expandTrue) table.add_column(Patron God) table.add_column(Population) table.add_column(Capital City) table.add_row(god, population, capital) return table def compose(self) - ComposeResult: yield Header() yield OptionList(*[self.colony(*row) for row in COLONIES]) yield Footer() if __name__ __main__: OptionListApp().run()完整示例见 docs/examples/widgets/option_list_tables.py。从源码结构看get_content_height与_update_lines每个选项的高度由渲染出的视觉内容高度决定多行选项会被当作多条终端行参与滚动与分页计算这正是选项高度任意的实现基础。响应式属性Reactive AttributesOptionList对外暴露的核心响应式属性如下见 源码名称类型默认值说明highlightedint \| NoneNone当前高亮选项的索引None表示没有任何选项被高亮compactboolFalse是否启用紧凑显示模式对应 CSS 类-textual-compacthighlighted的值在写入时会经过校验validate_highlighted小于 0 会收敛为 0超过列表末尾会收敛为len(options) - 1。当高亮变化且目标选项未被禁用时组件会自动滚动到该选项并发布OptionHighlighted消息watch_highlighted。通过highlighted_option属性可以直接获取当前高亮对应的Option对象源码option: Option | None option_list.highlighted_option消息MessagesOptionList会发布两类消息OptionList.OptionHighlighted当某个选项被高亮时发布。OptionList.OptionSelected当某个选项被选中时发布。两者都继承自共同的基类OptionList.OptionMessage因此都具备以下属性见 源码属性类型说明option_listOptionList发送该消息的 OptionList 实例optionOption消息所涉及的选项对象option_idstr \| None该选项的 IDoption.id的别名option_indexint该选项在列表中的索引controlOptionListoption_list的别名供on装饰器使用处理方式与 Textual 其他消息一致——在 App 或父级组件中定义on_option_list_option_highlighted/on_option_list_option_selected方法即可。测试 tests/option_list/test_option_messages.py 演示了这两个处理器的签名写法例如def on_option_list_option_selected(self, event: OptionList.OptionSelected) - None: self.selected_message fSelected {event.option.prompt}绑定键位BindingsOptionList定义了以下默认按键绑定见 源码按键动作说明downcursor_down高亮向下移动upcursor_up高亮向上移动homefirst高亮移动到第一个选项endlast高亮移动到最后一个选项pagedownpage_down高亮向下翻一页pageuppage_up高亮向上翻一页enterselect选中当前高亮选项所有绑定在 Footer 中默认隐藏showFalse。这些动作对应的实现方法action_cursor_up、action_cursor_down、action_first、action_last、action_page_up、action_page_down、action_select位于 源码上下移动通过_widget_navigation.find_next_enabled实现会跳过被禁用的选项因此高亮始终停留在可交互的选项上分页移动通过_move_page按可视区域高度估算行距并使用find_next_enabled_no_wrap在目标附近收敛到可用的选项action_select在存在高亮且高亮选项未禁用时发布OptionSelected消息。鼠标交互同样受支持点击未禁用选项会将其高亮并立即选中_on_click鼠标悬停会触发option-list--option-hover样式_on_mouse_move。组件类Component ClassesOptionList提供了以下组件类可用于在 CSS 中精细化定制各状态的外观见 源码类名说明option-list--option默认状态未禁用、未高亮、鼠标未悬停的选项option-list--option-disabled被禁用的选项option-list--option-highlighted被高亮的选项option-list--option-hover鼠标悬停的选项option-list--separator分隔线其默认 CSSDEFAULT_CSS展示了这些类的典型用法与默认外观OptionList { height: auto; max-height: 100%; color: $foreground; overflow-x: hidden; border: tall $border-blurred; padding: 0 1; background: $surface; } OptionList:focus { border: tall $border; background-tint: $foreground 5%; }聚焦时高亮选项会采用$block-cursor-*主题色未聚焦时采用对应的$block-cursor-blurred-*模糊色。你可以通过覆盖这些组件类来定制自己的配色OptionList .option-list--option-highlighted { background: $success; color: $text; text-style: bold; }常用 API 一览除构造参数*content选项内容、name、id、classes、disabled、markup、compact外OptionList还提供了丰富的增删改查方法均支持链式调用并返回self方法说明add_option(option)/add_options(options)向列表末尾添加选项传None表示添加分隔线set_options(options)清空现有选项后整体替换见 tests/option_list/test_option_list_create.pyclear_options()清空全部选项并重置高亮与滚动位置get_option(option_id)按 ID 获取Option不存在则抛OptionDoesNotExistget_option_index(option_id)按 ID 获取选项索引get_option_at_index(index)按索引获取Option越界抛OptionDoesNotExistenable_option(option_id)/disable_option(option_id)按 ID 启用 / 禁用选项另有_at_index版本remove_option(option_id)/remove_option_at_index(index)删除指定选项replace_option_prompt(option_id, prompt)/replace_option_prompt_at_index(index, prompt)替换选项的提示内容scroll_to_highlight(topFalse)滚动到当前高亮选项topTrue时将其置于组件顶部相关异常见 源码OptionListError选项列表错误的基类DuplicateID添加了重复 ID 的选项时抛出OptionDoesNotExist按不存在的 ID 或越界索引查询时抛出。Option同样支持子类化以携带额外数据测试 tests/option_list/test_option_list_option_subclass.py 展示了自定义OptionWithExtras并添加 100 个实例的用法。底层实现要点从源码结构看OptionList在渲染层面做了如下优化渲染缓存使用LRUCache容量 2048按(option, style, padding)缓存已渲染的行_get_option_render选项内容变化或组件尺寸变化_on_resize时清空缓存行缓存通过_LineCache记录选项索引 → 终端行的映射支持任意高度选项的滚动定位_update_lines分隔线渲染None添加的分隔线通过将前一个选项标记_divider True实现add_options渲染时在选项下方追加一条─组成的横线行高计算与虚拟尺寸计算都会把这条线纳入考虑。小结OptionList是 Textual 中构建单选式菜单与选择界面的高效组件字符串构造开箱即用Option实例带来 ID 与禁用状态控制Rich renderable 支持让选项可以承载表格、富文本等任意高度的内容配合highlighted响应式属性、OptionHighlighted/OptionSelected消息、完整的键盘导航绑定与细粒度的组件类样式足以覆盖从简单命令菜单到复杂数据浏览面板的各类场景。【免费下载链接】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),仅供参考

相关新闻

Streamlit 前端 TypeScript 开发指南:从代码规范到性能热路径的工程实践

Streamlit 前端 TypeScript 开发指南:从代码规范到性能热路径的工程实践

Streamlit 前端 TypeScript 开发指南:从代码规范到性能热路径的工程实践 【免费下载链接】streamlit Streamlit — A faster way to build and share data apps. 项目地址: https://gitcode.com/gh_mirrors/st/streamlit 导读 本文基于 Streamlit 仓库 fron…

2026/9/19 7:35:25 阅读更多 →
first-contributions 开源贡献入门实战:从 Fork 到 Pull Request 的完整命令行工作流

first-contributions 开源贡献入门实战:从 Fork 到 Pull Request 的完整命令行工作流

first-contributions 开源贡献入门实战:从 Fork 到 Pull Request 的完整命令行工作流 【免费下载链接】first-contributions 🚀✨ Help beginners to contribute to open source projects 项目地址: https://gitcode.com/gh_mirrors/fi/first-contribu…

2026/9/19 7:35:25 阅读更多 →
Node.js 25.5.0 发布深度解读:`--build-sea` 一步构建单文件可执行应用(SEA)与多项新特性

Node.js 25.5.0 发布深度解读:`--build-sea` 一步构建单文件可执行应用(SEA)与多项新特性

Node.js 25.5.0 发布深度解读:--build-sea 一步构建单文件可执行应用(SEA)与多项新特性 【免费下载链接】nodejs.org The Node.js Website 项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.org 导读 本文基于 nodejs.org 官…

2026/9/19 7:34:25 阅读更多 →

最新新闻

x64dbg 插件 API 深度解析:GuiReferenceGetCellContent 读取 Reference View 单元格数据

x64dbg 插件 API 深度解析:GuiReferenceGetCellContent 读取 Reference View 单元格数据

x64dbg 插件 API 深度解析:GuiReferenceGetCellContent 读取 Reference View 单元格数据 【免费下载链接】x64dbg An open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis. 项目地址: https://gitcode.com/gh_m…

2026/9/19 8:19:42 阅读更多 →
如何用Elasticsearch Chart在Kubernetes构建多角色集群:master到data节点完整配置指南

如何用Elasticsearch Chart在Kubernetes构建多角色集群:master到data节点完整配置指南

如何用Elasticsearch Chart在Kubernetes构建多角色集群:master到data节点完整配置指南 【免费下载链接】charts ⚠️(OBSOLETE) Curated applications for Kubernetes 项目地址: https://gitcode.com/gh_mirrors/chart/charts 在 Kubernetes 中部署 Elastics…

2026/9/19 8:19:42 阅读更多 →
系统动力学与Vensim实战:区域碳减排政策仿真建模全流程解析

系统动力学与Vensim实战:区域碳减排政策仿真建模全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 8:19:42 阅读更多 →
PHP票务系统实名核验实战:海宇二要素V即时版接口集成与合规留痕

PHP票务系统实名核验实战:海宇二要素V即时版接口集成与合规留痕

1. 从一张票的合规链路说起:为什么O2O票务绕不开运营商二要素做O2O票务系统的朋友大概率都遇到过这种场景:用户在App上选好场次、座位,点了"提交订单",后台却卡在实名核验这一步——要么是用户手滑把手机号填错了一位&a…

2026/9/19 8:19:42 阅读更多 →
Win11彻底卸载手机连接:PowerShell命令与预装应用清理指南

Win11彻底卸载手机连接:PowerShell命令与预装应用清理指南

1. 为什么我要彻底干掉 Win11 的“手机连接”“手机连接”这个组件,在 Win11 里叫Phone Link,早期叫 Your Phone。微软把它预装在系统里,本意是让 Android 和 iPhone 用户能在电脑上收发短信、看通知、传照片。听起来挺美好,但实际…

2026/9/19 8:19:42 阅读更多 →
Pace快速上手教程:仅3行代码,给你的网站加上自动加载进度条

Pace快速上手教程:仅3行代码,给你的网站加上自动加载进度条

Pace快速上手教程:仅3行代码,给你的网站加上自动加载进度条 【免费下载链接】pace Automatically add a progress bar to your site. 项目地址: https://gitcode.com/gh_mirrors/pa/pace Pace 是一款自动加载进度条插件(npm 包名 pace…

2026/9/19 8:18:42 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/19 4:02:43 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →