Flet 事件详解:DismissibleUpdateEvent 拖拽更新事件的结构、字段与实战用法
2026/9/24 21:22:34 网站建设 项目流程
  • 前端
  • 跨平台
  • 桌面应用
  • 移动开发

【免费下载链接】flet

Build realtime web, mobile and desktop apps in Python only. No frontend experience required.

项目地址:https://gitcode.com/gh_mirrors/fl/flet
点击查看免费下载

DismissibleUpdateEvent是 Flet 中Dismissible控件在用户拖拽(dismiss 手势)过程中持续触发的事件负载(event payload)。它通过on_update回调向 Python 侧实时上报拖拽方向、进度、是否越过"可撤销删除阈值"等状态,是实现"滑动删除前预览进度、到达阈值给出视觉反馈、跨过阈值后执行删除"等交互的关键数据源。读完本文,你将掌握该事件的全部字段语义、底层触发链路,以及结合dismiss_thresholdsconfirm_dismiss的完整实战写法。

事件概述:拖拽过程中实时上报的"进度快照"

DismissibleUpdateEvent定义于 Python 源码 dismissible.py,其类文档明确说明它是在 "a dismiss gesture is in progress"(拖拽手势进行中)时发出的负载。与DismissibleDismissEvent(在确认/完成撤销后触发)不同,DismissibleUpdateEvent的特点是高频、连续:只要用户按住内容进行拖拽,就会持续派发,让应用能够逐帧感知手势状态。

它与Dismissible控件的on_update回调直接绑定:

ft.Dismissible( content=ft.ListTile(title=ft.Text("Item")), on_update=handle_update, # 拖拽过程中持续触发 )

从源码结构看,DismissibleUpdateEvent继承自flet.controls.control_event.Event(control_event.py),因此它同样自带name(事件名)、control(触发事件的控件实例)、page(事件所属页面)等通用字段,方便在回调里访问父级控件与页面上下文。

字段详解:direction / progress / reached / previous_reached

DismissibleUpdateEvent共定义 4 个专属字段,全部来自 Flutter 框架Dismissible.onUpdate回调的DismissUpdateDetails参数。逐一定义如下(引用自 dismissible.py):

字段类型语义取值范围/说明
directionDismissDirection当前拖拽手势的方向见下文枚举说明
progressfloat拖拽进度相对于撤销阈值的0.0~1.0
reachedbool当前是否已达到撤销阈值True表示本次更新时已越过阈值
previous_reachedbool上一次更新事件时是否已达到阈值用于检测"刚刚越界"或"刚刚退回"的边沿变化

其中progressreached的组合是最常用的判断依据:progress给出连续进度(可用于驱动背景色渐变、图标缩放等过渡动画),而reached给出离散的布尔状态(决定是否显示"松开即可删除"的提示)。

previous_reached则解决了reached本身无法表达"状态刚刚发生变化"的问题——通过比较reached != previous_reached,应用可以精确捕获"刚刚越过阈值"(reached=True, previous_reached=False)与"刚刚拖回阈值内"(reached=False, previous_reached=True)这两个边沿时刻,从而只在这些瞬间执行一次性的反馈逻辑(如震动、播放音效)。

direction 的取值:DismissDirection 枚举

direction字段的类型DismissDirection是枚举类,定义于 snack_bar.py(与SnackBar共用同一枚举):

  • NONE:禁用滑动撤销手势;
  • VERTICAL:允许向上或向下滑动撤销;
  • HORIZONTAL:允许向左或向右滑动撤销(Dismissible.dismiss_direction的默认值);
  • END_TO_START:沿"尾端到起始端"阅读方向滑动(LTR 语言即从右往左);
  • START_TO_END:沿"起始端到尾端"阅读方向滑动(LTR 语言即从左往右);
  • UP/DOWN:仅允许向上 / 仅允许向下滑动撤销。

注意END_TO_STARTSTART_TO_END感知语言方向(locale-aware)的,在从右到左(RTL)语言环境中方向会反转,适合需要国际化适配的列表删除交互。

底层链路:从 Flutter 手势到 Python 事件的完整数据流

DismissibleUpdateEvent的触发链路横跨 Flutter 端与 Python 端,理解它有助于排查"事件不触发"或"字段为 None"等问题:

  1. Flutter 端DismissibleControl构建 Flutter 原生Dismissible控件,并把onUpdate回调绑定为"将DismissUpdateDetails序列化后触发 update 事件"(dismissible.dart);
  2. 序列化:Dart 侧DismissibleUpdateEvent.toMap()directionprogressreachedprevious_reached四个字段打包为 JSON(dismissible.dart),其中directiondetails.direction.name字符串值;
  3. 传输与反序列化:事件经 Flet 的通信通道送达 Python 侧,由Dismissible控件的事件处理机制反序列化为flet.DismissibleUpdateEvent实例;
  4. Python 回调:最终调用on_update绑定的处理函数。

关键点:Dart 端只有在widget.control.hasEventHandler("update")为真时才会绑定onUpdate(dismissible.dart),因此不写on_update回调就不会产生任何 update 事件,这是对性能的有意优化——高频拖拽事件不会在无人监听时白白穿过通信链路。

实战示例:滑动删除列表中的实时进度反馈

仓库示例 dismissible_list_tiles/main.py 完整演示了DismissibleUpdateEvent的接入方式。下面是一个在示例基础上扩展了"阈值边沿检测"的完整可运行代码:

import flet as ft def main(page: ft.Page): def handle_update(e: ft.DismissibleUpdateEvent): # 打印事件负载,观察 direction / progress / reached / previous_reached print(e) # 边沿检测:刚刚越过阈值 if e.reached and not e.previous_reached: print(f"Item 即将被删除:direction={e.direction}, progress={e.progress:.2f}") # 刚刚拖回阈值内 if not e.reached and e.previous_reached: print("已取消删除,拖回原位") # 用 progress 驱动中间态(例如 0~50% 提示"继续滑动") if not e.reached and e.progress > 0.3: print("继续滑动以删除……") def handle_dismiss(e: ft.Event[ft.Dismissible]): # 真正被删除后,从列表移除该行 e.control.parent.controls.remove(e.control) e.control.parent.update() page.add( ft.SafeArea( content=ft.ListView( expand=True, controls=[ ft.Dismissible( dismiss_direction=ft.DismissDirection.HORIZONTAL, background=ft.Container(bgcolor=ft.Colors.GREEN), secondary_background=ft.Container(bgcolor=ft.Colors.RED), on_update=handle_update, on_dismiss=handle_dismiss, dismiss_thresholds={ ft.DismissDirection.END_TO_START: 0.2, ft.DismissDirection.START_TO_END: 0.2, }, content=ft.ListTile(title=ft.Text(f"Item {i}")), ) for i in range(10) ], ), ) ) if __name__ == "__main__": ft.run(main)

要点说明:

  • dismiss_thresholds以字典形式按方向分别设置阈值(取值0.0~1.0之间的小数),即progress达到1.0所对应的拖拽比例。示例中把左右两个方向都设为0.2,意味着内容被拖出自身宽度 20% 即视为"达到阈值";
  • reachedprevious_reached正是围绕dismiss_thresholds计算出来的:当前拖拽比例 ≥ 阈值时reached=True,否则为False
  • 若未设置on_dismiss,即使拖过阈值松手,内容也只会弹回原位,不会执行删除——真正删除仍由on_dismiss(或on_confirm_dismiss+confirm_dismiss)负责。

与 on_confirm_dismiss 协同:先预览、后确认

DismissibleUpdateEvent常用于"预览阶段"的反馈,而确认逻辑由Dismissible的另一组回调承担:

  • on_update:拖拽进行中,实时反馈(本文主题);
  • on_confirm_dismiss:拖拽松手且达到阈值后触发,给应用一个"确认或否决"的机会,此时控件会被锁定无法再次拖拽,直到调用confirm_dismiss(bool)解决挂起的决策(dismissible.py);
  • on_dismiss:内容完成收缩动画、确认撤销后触发。

仓库示例 dismissible_list_tiles/main.py 展示了典型组合:在on_confirm_dismiss中弹出AlertDialog让用户确认,确认后调用e.control.confirm_dismiss(True)完成删除,取消则传False让内容回到原位。在这一流程中,DismissibleUpdateEvent可以提前告知用户"当前拖拽已过阈值,松开将弹出确认框",避免误触。

调试建议

由于 update 事件是高频事件,直接打印事件对象即可快速观察字段变化规律:

def handle_update(e: ft.DismissibleUpdateEvent): print(e) # 观察 direction / progress / reached / previous_reached

若事件始终不触发,按以下顺序排查:

  1. 是否在Dismissible上绑定了on_update(未绑定则 Dart 端不注册onUpdate,参见 dismissible.dart);
  2. 是否设置了dismiss_direction且手势方向与之一致(例如仅UP时左右拖拽不会触发 update);
  3. 控件是否可见——Dismissible.content必须是可见控件(dismissible.py)。

延伸阅读

  • 控件完整属性与全部事件:Dismissible 控件文档
  • 事件基类(name/data/control/page字段):Event 类型文档
  • 同族事件DismissibleDismissEvent:与DismissibleUpdateEvent同文件定义(dismissible.py),承载on_confirm_dismiss/on_dismissdirection信息
  • 完整运行示例:dismissible_list_tiles/main.py
  • 前端
  • 跨平台
  • 桌面应用
  • 移动开发

【免费下载链接】flet

Build realtime web, mobile and desktop apps in Python only. No frontend experience required.

项目地址:https://gitcode.com/gh_mirrors/fl/flet
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询