尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Flet Semantics 控件全解析:为 Python 应用构建无障碍语义树

Flet Semantics 控件全解析:为 Python 应用构建无障碍语义树 Flet Semantics 控件全解析为 Python 应用构建无障碍语义树【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/fletSemantics 是 Flet 中负责为控件树附加语义注解Semantic Annotations的核心控件它向屏幕阅读器等辅助技术、搜索引擎与语义分析软件描述界面元素的意义与用途。本文基于flet.Semantics控件源码与仓库内示例系统讲解其全部属性、事件模型、无障碍焦点监听以及内置的语义调试器用法帮助你用纯 Python 为 Web、移动端与桌面端应用补齐可访问性Accessibility能力。Semantics 控件是什么从源码定义看flet.Semantics是一个用于包裹其他控件的语义包装器。在 sdk/python/packages/flet/src/flet/controls/core/semantics.py 中它通过control(Semantics)注册为一个标准 Flet 控件control(Semantics) class Semantics(Control): Provides semantic annotations for the control tree, describing the meaning and \ purpose of controls. These annotations are utilized by accessibility tools, search engines, and semantic analysis software to better understand the structure and functionality of the application. 它的核心价值在于Flutter 渲染层本身会为每个控件自动生成部分语义信息但纯视觉的自定义组合例如用RowIconButton拼出的计数器对辅助工具而言往往是不可读的。用Semantics包裹后你可以显式声明这块区域是什么、当前处于什么状态、可以被执行哪些操作从而让读屏软件TalkBack、VoiceOver和搜索引擎正确理解你的界面。在 Flutter 端packages/flet/lib/src/controls/semantics.dart 中的SemanticsControl把 Python 端传来的属性逐一映射到 Flutter 官方SemanticsWidget 上例如label映射到label、hint_text映射到hint、focus映射到focused。这意味着你掌握的 Flet 语义参数与 Flutter 语义模型是一一对应的。完整示例为输入框添加语义标签仓库中flet.Semantics的官方示例位于 sdk/python/examples/controls/core/semantics/semantics/main.py演示了最基础也是最典型的用法——给一个TextField附加语义标签并监听无障碍焦点获得/失去事件import flet as ft def main(page: ft.Page): def handle_gain_accessibility_focus(e: ft.Event[ft.Semantics]): print(focus gained) def handle_lose_accessibility_focus(e: ft.Event[ft.Semantics]): print(focus lost) page.add( ft.SafeArea( contentft.Column( controls[ ft.Semantics( labelInput your occupation, on_did_gain_accessibility_focushandle_gain_accessibility_focus, on_did_lose_accessibility_focushandle_lose_accessibility_focus, contentft.TextField( labelOccupation, hint_textUse 20 words or less, valueWhat is your occupation?, ), ), ft.Icon(ft.Icons.SETTINGS, color#c1c1c1), ] ), ) ) if __name__ __main__: ft.run(main)运行这段代码后屏幕阅读器会把该输入框朗读为Input your occupation而非读取内部的提示文字当用户通过读屏导航进入或离开该区域时Python 侧的print会分别输出focus gained与focus lost。这就是语义注解最基本、最直接的收益。属性详解完整参数清单与语义含义Semantics的属性全部定义在 semantics.py 中。按其作用可分为四类内容与文本、状态描述、角色声明、行为开关。内容与文本描述属性类型说明contentControl被注解的控件必填。若缺失或不可见Flutter 端会渲染ErrorControl提示Semantics.content must be provided and visiblelabelstr对content的文字描述读屏软件朗读的主要内容valuestr对content当前值value的文字描述hint_textstr对在content上执行操作后结果的简要说明on_tap_hint_textstr用户触发on_tap时发生什么的提示辅助技术会将其与hint_text一起播报on_long_press_hint_textstr用户触发on_long_press时发生什么的提示tooltipstr控件工具提示的文字描述badgeBadgeValue徽标语义源码注释标注为 TBD处于待完善状态状态描述属性类型说明expandedbool子树是否表示可展开/折叠的节点及其当前状态hiddenbool子树当前是否隐藏selectedbool子树是否表示可选中/取消选中的节点及其当前状态checkedbool子树是否表示复选框类控件及其当前勾选状态toggledbool子树是否表示开关类控件及其当前开状态mixedbool子树是否表示带半勾选状态的控件以及当前是否处于该状态focusbool节点当前是否持有输入焦点Flutter 端映射为focusedfocusablebool节点是否能够持有输入焦点read_onlybool子树是否只读obscuredboolvalue是否应被遮蔽如密码输入multilineboolvalue是否来自支持多行文本编辑的输入域max_value_lengthNumber可编辑文本域允许输入的最大字符数current_value_lengthint可编辑文本域当前已输入的字符数角色声明属性类型说明buttonbool子树是否表示一个按钮sliderbool子树是否表示一个滑块textfieldbool子树是否表示一个文本输入域linkbool子树是否表示一个链接headerbool子树是否表示一个标题/页眉imagebool节点是否表示一张图片heading_levelint在 DOM 文档结构中的标题层级帮助读屏用户快速跳转行为开关属性类型说明exclude_semanticsbool默认False。为True时content自身携带的语义信息被排除仅暴露当前Semantics包装器上显式配置的语义containerbool默认False。为True时该语义节点会引入自己的语义容器将子树语义聚合成独立节点而不是总是与周围语义合并live_regionbool子树是否应被视为实时区域live region内容变化时读屏软件主动播报以container为例其源码注释明确解释了用途A container groups the semantics of its subtree into a distinct node instead of always merging with surrounding semantics见 semantics.py。当一个控件被其他控件的语义吸收合并时设置containerTrue可以强制它成为一个独立的语义节点这是排查读屏播报混乱时的重要开关。事件模型响应用户的语义操作Semantics不仅描述界面还能响应用户通过辅助方式手势、语音、键盘发起的语义操作。全部事件定义见 semantics.py事件触发时机on_tap节点被点击时on_long_press节点被长按时on_increase/on_decrease节点表示的数值被增大/减小时如滑块、步进器on_dismiss节点被消除时on_scroll_left/on_scroll_right手指从右向左 / 从左向右划过屏幕on_scroll_up/on_scroll_down手指从下向上 / 从上向下划过屏幕on_copy/on_cut/on_paste当前选区被复制 / 剪切 / 粘贴到剪贴板时on_move_cursor_forward_by_character光标向前移动一个字符on_move_cursor_backward_by_character光标向后移动一个字符on_set_text用户想用新文本替换文本域内容时Android 上的 Voice Access 用户可通过语音输入type text触发on_did_gain_accessibility_focus节点获得无障碍焦点时on_did_lose_accessibility_focus节点失去无障碍焦点时on_double_tap保留事件源码明确警告Reserved for a semantic double-tap action当前运行时未接线not wired在控件实现支持之前不会触发在 Flutter 端这些事件通过control.triggerEvent(...)回传见 semantics.dart其中on_tap对应事件名click与 Flet 中其他控件的点击事件保持一致带参数的事件如on_set_text、光标移动会把文本内容或布尔值一并回传。实战案例用 Semantics 包装可访问计数器仓库中的 sdk/python/examples/apps/counter/accessible/main.py 是一个完整的无障碍计数器应用展示了多个核心语义参数的组合用法import flet as ft def main(page: ft.Page): page.title Counter page.vertical_alignment ft.MainAxisAlignment.CENTER txt_number ft.TextField( value0, text_alignft.TextAlign.RIGHT, width100, labelCounter value, ) def toggle_semantics_debugger(e): page.show_semantics_debugger not page.show_semantics_debugger page.update() def minus_click(e): txt_number.value str(int(txt_number.value) - 1) txt_number.label fCounter value, {txt_number.value} page.update() def plus_click(e): txt_number.value str(int(txt_number.value) 1) txt_number.label fCounter value, {txt_number.value} page.update() page.on_keyboard_event toggle_semantics_debugger page.add( ft.SafeArea( contentft.Column( horizontal_alignmentft.CrossAxisAlignment.CENTER, controls[ ft.Semantics( label( Press plus button to increase counter, or minus button to decrease counter. ), hint_text( Press CONTROL plus ALT plus S to show semantics debugger ), buttonTrue, contentft.Row( alignmentft.MainAxisAlignment.CENTER, controls[ ft.IconButton( iconft.Icons.REMOVE, tooltipDecrease number, on_clickminus_click, ), txt_number, ft.IconButton( iconft.Icons.ADD, tooltipIncrease number, on_clickplus_click, ), ], ), ), ft.Text( value( Press CONTROL plus ALT plus S to show semantics debugger ), ), ], ) ) ) if __name__ __main__: ft.run(main)这个例子有几个值得注意的实践要点buttonTrue声明整块区域在语义层面是一个按钮读屏软件会提示用户可以激活它label提供区域整体的操作指引hint_text补充调试器快捷键说明计数变化时同步更新txt_number.label确保读屏播报的是最新数值键盘事件被用来切换page.show_semantics_debugger这是 Flet 内置语义调试器的标准开关方式。语义调试器可视化检查无障碍信息page.show_semantics_debugger是Page的内置属性定义于 sdk/python/packages/flet/src/flet/controls/base_page.pyshow_semantics_debugger: bool False Whether to turn on an overlay that shows the accessibility information reported by \ the framework. 当它为True时应用会开启一个覆盖层实时显示框架上报的辅助功能信息——每个节点暴露的 label、role、state 等都会被可视化呈现是验证语义配置是否生效的最直接手段。仓库提供了独立的调试器演示 sdk/python/examples/controls/core/page/semantics_debugger/main.py按下ShiftS即可切换调试器开关def on_keyboard(e: ft.KeyboardEvent): if e.shift and e.key S: page.show_semantics_debugger not page.show_semantics_debugger page.update() page.on_keyboard_event on_keyboard在 Flutter 端show_semantics_debugger会被读取并传入MaterialApp/CupertinoApp的showSemanticsDebugger参数见 packages/flet/lib/src/controls/page.dart从而复用 Flutter 框架原生的语义调试覆盖层。常见问题与建议1. Semantics 包裹后没效果先检查content是否可见。Flutter 端在content缺失或不可见时会渲染ErrorControl并在日志打印Semantics.content must be provided and visible见 semantics.dart。2. 子控件的语义被意外合并这是 Flutter 语义树的默认合并行为。如果希望某块区域成为独立语义节点设置containerTrue如果希望完全屏蔽子控件自带的语义、只保留自己声明的 label设置exclude_semanticsTrue。3. 如何验证读屏效果开发阶段开启page.show_semantics_debugger可视化检查语义覆盖层真机阶段使用系统自带的 TalkBackAndroid或 VoiceOveriOS实测播报内容。4.on_double_tap为什么收不到事件这是当前运行时的已知限制源码标注该事件Reserved尚未接线触发前需要控件实现层补充支持请勿依赖此事件。5. 何时应该用 Semantics当界面由自定义组合控件Row、Stack、GestureDetector 等构成、而读屏软件无法推断其含义时当文本输入需要播报占位/值/长度信息时当需要响应语音或辅助手势操作时。注意Flet 的许多内置控件Button、Checkbox、Switch、TextField 等自身已携带语义无需额外包裹。延伸阅读与Semantics搭配使用的同类控件还有MergeSemantics用于把子树语义合并为一个整体参见 website/docs/controls/mergesemantics.md控件属性与事件的完整定义sdk/python/packages/flet/src/flet/controls/core/semantics.pyFlutter 端语义映射实现packages/flet/lib/src/controls/semantics.dart可运行示例controls/core/semantics/semantics/main.py 与 apps/counter/accessible/main.py语义调试器示例controls/core/page/semantics_debugger/main.py。【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表