主题
Flet 会在每个事件处理器和 main() 函数结束时自动调用 page.update()(或最近隔离祖先控件的 .update())。 这意味着你在大多数情况下不需要自己调用 .update():
python
import flet as ft
def main(page: ft.Page):
def button_click(e):
page.controls.append(ft.Text("Clicked!"))
# no need to call page.update() — it happens automatically
page.controls.append(ft.Button("Click me", on_click=button_click))
# no need to call page.update() here either
ft.run(main)注意
如果你的事件处理器已经显式调用了 .update()(例如为 Flet 0.x 编写的代码),Flet 会跳过自动更新,以避免冗余的双重更新。
在处理程序中途更新
由于更新是在处理器结束时才发送的,一个包含循环的处理器在返回之前不会显示任何内容。要在处理器中途推送一次更新,可将其写成生成器 —— 每一次 yield 都会刷出待发的更新,并让事件循环得以运行:
python
import flet as ft
def main(page: ft.Page):
progress = ft.ProgressBar(value=0)
def process(e):
for i in range(10):
do_chunk(i)
progress.value = (i + 1) / 10
yield # 进度条在此处前进
page.add(progress, ft.Button(content="Process", on_click=process))
ft.run(main)异步处理器同样可以 yield。await 会让其他任务得以运行,但它本身并不会触发 Flet 的自动更新。在修改控件之后 yield,即可发布中间进度:
python
async def process(e):
for i in range(10):
await asyncio.to_thread(do_chunk, i)
progress.value = (i + 1) / 10
yield另一种做法:保留普通的异步处理器,并在每次赋值后调用 progress.update()。下一次 await 会给连接一个发送更新的机会。
让每个分块保持短小
生成器处理器仍然运行在事件循环上,因此在两次 yield 之间 UI 是被阻塞的。如果一个分块长到足以被察觉,就把它移出事件循环 —— 参见 异步应用。
关闭自动更新
你可以关闭自动更新,以便精细控制更新何时发送到客户端。使用 ft.context.disable_auto_update() 和 ft.context.enable_auto_update() 来切换此行为。
在事件处理器内部调用时,该设置只适用于当前的事件处理器上下文:
python
import flet as ft
def main(page: ft.Page):
def add_many_items(e):
ft.context.disable_auto_update()
for i in range(100):
page.controls.append(ft.Text(f"Item {i}"))
page.update() # single update for all 100 items
page.controls.append(ft.Button("Add items", on_click=add_many_items))
ft.run(main)在事件处理器之外调用时(例如在模块级别),它控制的是整个应用的全局默认值:
python
import flet as ft
# disable auto-update globally
ft.context.disable_auto_update()
def main(page: ft.Page):
def button_click(e):
page.controls.append(ft.Text("Clicked!"))
page.update() # must call explicitly since auto-update is off
page.controls.append(ft.Button("Click me", on_click=button_click))
page.update()
ft.run(main)