多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Flet 中的 Control 基类完全指南:通用属性、响应式布局与控件生命周期机制

Flet 中的 Control 基类完全指南:通用属性、响应式布局与控件生命周期机制 前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载Control对应 API 参考中的flet.control是 Flet 框架中所有 UI 控件的基类无论是Text、Button还是TextField它们都从该类继承统一的属性体系与生命周期钩子。本文以 flet.control 参考页 为骨架结合仓库内 control.py 与 base_control.py 的源码实现系统讲解每个 Flet 控件开箱即用的通用能力——可见性与交互控制、布局扩展、响应式栅格、视觉呈现以及从挂载到卸载的完整生命周期帮助你在开发时准确理解控件行为、减少调试成本。一、认识 Control所有 Flet 控件的公共基类Flet 的类型参考页中flet.control通过ClassAll nameflet.control /组件见 ClassAll.js动态渲染自 Python 源码的 docstring其真实实体是源码中的两层类结构BaseControl定义控件与页面通信所需的运行时基础设施内部 ID、事件分发、更新机制、生命周期钩子定义于 base_control.py。Control(BaseControl)在其之上补充面向业务开发的通用属性布局、可见性、透明度、角标等定义于 control.py。源码的 docstring 明确指出Base class for controls. Not meant to be used directly.——即Control不应被直接实例化而是作为所有具体控件的父类存在。每一个你写进page.add(...)的控件本质上都是一个携带通用属性的Control子类实例。从 control 装饰器看控件如何接入框架在 Flet 中每个具体控件类都通过control装饰器声明其 Dart 侧对应的 widget 名称并接入数据类机制。查看 base_control.py 可知该装饰器支持四种用法# 1) 裸装饰器按 dataclass 规则处理 control class MyControl(BaseControl): ... # 2) 指定 Dart 侧 widget 名称 control(MyWidget) class MyControl(BaseControl): ... # 3) 同时指定 post_init_args 与隔离标记 control(MyWidget, post_init_args1, isolatedTrue) class MyControl(BaseControl): ... # 4) 附加 MCP 元数据供 Flet MCP 服务发现控件 control(MyWidget, categories(input,), tags(text,)) class MyControl(BaseControl): ...其中_apply_control会先调用dataclass(**dataclass_kwargs)(cls)再安装用于稀疏属性跟踪的Prop描述符并在__post_init__中把_cDart 侧类型名与_isolated写入实例。这解释了为什么 Flet 的每个控件都可以像普通 Python 对象一样直接赋值属性同时框架又能精确知道哪些属性发生了变化——这正是后面更新机制的基础。二、可见性与交互visible、disabled 与 rtlvisible控件是否渲染到画布visible: bool True源码注释control.py说明每个控件默认都渲染在页面上设为False后该控件及其全部子控件完全不会渲染到画布且隐藏控件无法被键盘或鼠标聚焦、选中也不会发出任何事件。这意味着隐藏不仅仅是看不见而是整个从事件体系中移除适合做条件展示而不希望其参与交互的场景。disabled一键禁用整组控件disabled: bool False的显著特性是向下递归传播——设置后该控件及其所有后代控件都会被禁用。源码给出了一个经典表单场景control.pyimport flet as ft ft.Column( disabledTrue, # 一次禁用整个表单 controls[ ft.TextField(), ft.TextField(), ], )当表单处于提交中或只读状态时只需把disabled放在容器控件上无需逐个操作子控件。rtl右到左文本方向rtl: bool False用于控制文本方向control.py。对于阿拉伯语、希伯来语等从右向左书写的语言界面将该属性设为True即可让控件的文本方向切换为 RTL。三、布局扩展expand、expand_loose 与 colexpand填充父布局的剩余空间expand: Optional[Union[bool, int]] None源码指出control.py指定控件是否/如何扩展以填满父布局中的可用空间且仅当控件的直接父控件是Column、Row、View、Page或其子类之一时生效否则会被忽略ft.Row( controls[ ft.TextField(expandTrue), # 占据所有剩余空间 ft.TextField(expand2), # 占 2 份权重 ft.TextField(expand1), # 占 1 份权重 ], )传入True表示尽可能填满传入整数则按权重分配剩余空间如上面2:1的比例。类型校验不通过非bool或int时抛出ValueError。更完整的扩展场景说明可参考仓库文档 expanding-controls.md。expand_loose允许但不强制填满expand_loose: bool False是一个更宽松的扩展模式control.py如果主轴方向有可用空间控件可以扩展但不强制填满所有空间。它与expand配合使用且生效有两个前提条件expand不为None直接父控件是Column/Row/View/Page或其子类。典型场景是希望控件变宽一些但保留自然尺寸而不是撑满整行。colResponsiveRow 中的虚拟栅格col: ResponsiveNumber 12用于ResponsiveRow父容器control.py决定控件横跨屏幕的多少个虚拟列栅格总宽为 12 列。它既可以是一个数字也可以是为不同断点配置不同值的字典例如import flet as ft ft.ResponsiveRow( controls[ ft.TextField(col{sm: 6}), # 小屏及以上占一半宽度 ft.TextField(col12), # 默认占满整行 ft.TextField(col0), # 该断点下隐藏控件 ], )col0表示在当前断点下隐藏该控件即它不占用父ResponsiveRow的任何列。源码中内嵌的断点尺寸表如下断点屏幕尺寸xs 576pxsm≥ 576pxmd≥ 768pxlg≥ 992pxxl≥ 1200pxxxl≥ 1400pxResponsiveRow的完整用法可参见 responsiverow.md。四、视觉呈现opacity、tooltip 与 badgeopacity透明度opacity: Number 1.0control.py定义控件的透明度取值区间为0.0完全透明到1.0完全不透明默认值越界会抛出ValueError。常用于淡入淡出动画、置灰弱化等效果ft.Container( opacity0.4, # 半透明容器 contentft.Text(弱化内容), )tooltip悬停提示tooltip: Optional[TooltipValue] Nonecontrol.py当鼠标悬停在控件上时显示的提示文本可用于补充说明按钮或图标的含义ft.IconButton( iconft.icons.DELETE, tooltip删除该条目, )badge角标badge: Optional[BadgeValue] Nonecontrol.py在控件顶部叠加一个角标通常用来展示未读数量、状态标记等例如图标右上角的红色数字角标ft.IconButton( iconft.icons.NOTIFICATIONS, badgeft.Badge(text3), # 显示未读角标 )五、身份与状态data、key、ref、parent、pageBaseControl为每个控件定义了统一的身份与挂载信息base_control.pydata: Any任意类型的附加数据用于在控件上携带业务上下文不参与 UI 序列化。key: Optional[KeyValue] None稳定的键用于在多次更新中保持控件身份reconciliation 时据此匹配新旧实例避免状态丢失。ref: InitVar[Optional[Ref]]控件引用构造时传入refft.Ref()后可在任意位置通过ref.current拿到控件实例是 Flet 中命令式访问控件的标准手段。parent只读属性直接父控件默认None仅当控件被挂载进页面树后才有值Page作为树的根其parent恒为None。page只读属性控件所属的Page实例从当前节点向上遍历父链找到若控件尚未加入页面访问会抛出RuntimeErrorbase_control.py。import flet as ft txt ft.Text(hello) ref ft.Ref[ft.Text]() btn ft.ElevatedButton(refref, text点击, data{id: 42}) page.add(btn) assert btn.parent is page # 挂载后父控件为 Page assert btn.page is page # 归属页面 assert ref.current is btn # 通过 ref 访问同一实例 assert btn.data {id: 42} # 自定义数据原样保存六、控件生命周期从挂载到卸载的钩子方法BaseControl定义了完整的生命周期钩子base_control.py任何控件或自定义控件都可以重写它们钩子触发时机典型用途init()控件实例初始化完成后、首次构建/更新前轻量初始化不要在此调用update()build()控件初始化时调用一次定义子控件树此方法中可安全使用pagebefore_update()每次该控件被更新前更新前修正属性同样不要触发新的update()before_event(e)事件分发到处理器之前拦截事件返回False可取消分发did_mount()控件挂载进页面树之后启动订阅、定时器、服务监听等依赖page的资源will_unmount()控件从页面树移除之前释放did_mount()中创建的资源其中did_mount()与will_unmount()是一对遵循经典的资源成对申请与释放模式import flet as ft class TimerText(ft.Text): def did_mount(self): super().did_mount() self._timer self.page.run_task(self._tick) # 挂载后启动定时任务 async def _tick(self): # 周期性刷新控件内容... pass def will_unmount(self): super().will_unmount() # 取消任务、清理资源... passupdate()请求 UI 更新update()base_control.py是命令式更新的核心入口——在修改控件属性后调用把变更同步到前端txt ft.Text(初始文本) page.add(txt) txt.value 修改后的文本 txt.update() # 将属性变更推送到 UI源码中update()有两个前置校验控件若处于冻结状态_frozen或尚未加入页面会抛出RuntimeError。它最终委托给self.page.update(self)由页面统一进行差异计算与消息发送。七、事件分发on_ 处理器是如何被触发的尽管Control基类本身不定义具体事件但所有控件的事件都走BaseControl._trigger_event()这条统一管道base_control.py其内部流程可以概括为将事件名拼装为on_event_name字段名检查控件是否定义了对应处理器根据事件类型构建ControlEvent实例简单事件直接构造复杂事件通过from_dict反序列化调用before_event(e)若返回False则终止分发区分同步处理器、异步处理器协程、生成器处理器分别执行——这正是 Flet 支持async def on_click等异步事件处理器的底层机制对生成器型处理器每次yield都会触发一次after_event实现事件处理中途刷新 UI的分步更新能力。这意味着从源码结构看每个on_xxx处理器都是可选的——只要不定义对应事件就静默忽略一旦定义同步、异步、生成器三种写法都会被框架正确调度。八、进阶control 与自定义控件理解Control基类后开发自定义控件就变得非常直观继承Control或更具体的子类用control声明 Dart 侧 widget 名重写build()组织子控件必要时重写生命周期钩子。基类已经为你处理好了 ID 分配、属性跟踪、更新差异、事件分发与垃圾回收标识等全部样板逻辑你只需聚焦控件的业务表现。可进一步参考 user-extensions.md 与 custom-controls.md 了解扩展控件的完整流程。总结flet.control参考页背后是一套设计精良的控件基类体系Control层提供visible、disabled、rtl、expand、expand_loose、col、opacity、tooltip、badge等开箱即用的通用属性BaseControl层则承载data、key、ref、parent、page等身份信息与init/build/did_mount/will_unmount/update/_trigger_event等生命周期机制。无论你是日常使用内置控件、调试布局异常还是开发自定义控件掌握这套公共契约都能让你以更低的成本预测控件行为、写出更可靠的 Flet 应用。赞分享前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载相关推荐flet.Control 基类全解析Flet 控件体系的通用属性、布局与生命周期机制flet.Control 基类全解析Flet 控件体系的通用属性、布局与生命周期机制 flet.Control 是 Flet 框架中所有 UI 控件的公共基类前端跨平台桌面应用移动开发Flet 广告控件基类 BaseAd 完全指南统一广告单元、定位请求与生命周期事件Flet 广告控件基类 BaseAd 完全指南统一广告单元、定位请求与生命周期事件 导读 BaseAd 是 Flet 生态中 flet ads 扩展包内所有广前端跨平台桌面应用移动开发Yii2 应用对象Application完全指南配置、属性、事件与生命周期Yii2 应用对象Application完全指南配置、属性、事件与生命周期 导读 在 Yii2 中应用Application是掌管整个应用系统结后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表