python-flet

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Python Flet Development

Python Flet 开发

Flet is a Python framework for building cross-platform web, desktop, and mobile applications without prior frontend experience. It wraps Flutter widgets and exposes them as Python controls.
Flet 是一款Python框架,无需前端开发经验即可构建跨平台的网页、桌面和移动应用。它封装了Flutter组件,并将其以Python控件的形式对外提供。

App Entry Point

应用入口

Every Flet app has a
main
function receiving a
ft.Page
and ends with
ft.run(main)
:
python
import flet as ft

def main(page: ft.Page):
    page.title = "My App"
    page.add(ft.Text("Hello, Flet!"))

ft.run(main)
Installation:
pip install 'flet[all]'
Run desktop:
flet run main.py
Run web:
flet run --web main.py
Hot reload (watch directory recursively):
flet run --recursive main.py
每个Flet应用都有一个接收
ft.Page
参数的
main
函数,并以
ft.run(main)
结束:
python
import flet as ft

def main(page: ft.Page):
    page.title = "My App"
    page.add(ft.Text("Hello, Flet!"))

ft.run(main)
安装
pip install 'flet[all]'
运行桌面应用
flet run main.py
运行网页应用
flet run --web main.py
热重载(递归监听目录):
flet run --recursive main.py

Project Structure

项目结构

my-app/
├── pyproject.toml
└── src/
    ├── assets/
    │   └── icon.png
    └── main.py
Create via:
flet create
(or
uv run flet create
)
my-app/
├── pyproject.toml
└── src/
    ├── assets/
    │   └── icon.png
    └── main.py
创建方式:
flet create
(或
uv run flet create

Core Concepts

核心概念

Page

页面

ft.Page
is the root container. Configure it before adding controls:
python
def main(page: ft.Page):
    page.title = "App Title"
    page.theme_mode = ft.ThemeMode.LIGHT
    page.theme = ft.Theme(color_scheme_seed=ft.Colors.BLUE)
    page.vertical_alignment = ft.MainAxisAlignment.CENTER
    page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
    page.scroll = ft.ScrollMode.AUTO
ft.Page
是根容器,添加控件前需对其进行配置:
python
def main(page: ft.Page):
    page.title = "App Title"
    page.theme_mode = ft.ThemeMode.LIGHT
    page.theme = ft.Theme(color_scheme_seed=ft.Colors.BLUE)
    page.vertical_alignment = ft.MainAxisAlignment.CENTER
    page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
    page.scroll = ft.ScrollMode.AUTO

Controls and
update()

控件与
update()
方法

Controls are Python objects. Mutations require
page.update()
or
control.update()
:
python
text = ft.Text("Initial")
page.add(text)

def change(e):
    text.value = "Changed"
    text.update()          # prefer: update only this control
    # page.update()        # fallback: updates entire page
Rule: Prefer
control.update()
over
page.update()
— sends a smaller diff.
控件是Python对象,修改后需调用
page.update()
control.update()
python
text = ft.Text("Initial")
page.add(text)

def change(e):
    text.value = "Changed"
    text.update()          # 推荐:仅更新此控件
    # page.update()        # 备选:更新整个页面
规则:优先使用
control.update()
而非
page.update()
——仅发送更小的差异数据。

Layout Controls

布局控件

ControlPurpose
ft.Column
Vertical stack
ft.Row
Horizontal stack
ft.Stack
Absolute positioning
ft.Container
Box with padding, color, border, animation
ft.ListView
Efficient vertical/horizontal scrollable list
ft.GridView
Efficient scrollable grid
python
page.add(
    ft.Row(
        controls=[ft.Text("Left"), ft.Text("Right")],
        alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
    )
)
Expand: Use
expand=True
to fill available space:
python
ft.ListView(expand=True, spacing=10)
控件用途
ft.Column
垂直堆叠布局
ft.Row
水平堆叠布局
ft.Stack
绝对定位布局
ft.Container
带内边距、颜色、边框、动画的容器
ft.ListView
高效的垂直/水平滚动列表
ft.GridView
高效的滚动网格
python
page.add(
    ft.Row(
        controls=[ft.Text("Left"), ft.Text("Right")],
        alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
    )
)
扩展填充:使用
expand=True
填充可用空间:
python
ft.ListView(expand=True, spacing=10)

Custom Controls

自定义控件

Styled Controls (inherit a single Flet control)

样式化控件(继承单个Flet控件)

python
@ft.control
class PrimaryButton(ft.Button):
    bgcolor: ft.Colors = ft.Colors.BLUE_700
    color: ft.Colors = ft.Colors.WHITE
Use
@ft.control
or
@dataclass
decorator. Field types must be annotated.
python
@ft.control
class PrimaryButton(ft.Button):
    bgcolor: ft.Colors = ft.Colors.BLUE_700
    color: ft.Colors = ft.Colors.WHITE
使用
@ft.control
@dataclass
装饰器,字段必须标注类型。

Composite Controls (combine multiple controls)

复合控件(组合多个控件)

python
@ft.control
class TaskItem(ft.Row):
    text: str = ""

    def init(self):
        self.checkbox = ft.Checkbox()
        self.label = ft.Text(value=self.text)
        self.controls = [self.checkbox, self.label]

    def toggle(self, e):
        self.label.color = ft.Colors.GREY if self.checkbox.value else None
        self.update()
python
@ft.control
class TaskItem(ft.Row):
    text: str = ""

    def init(self):
        self.checkbox = ft.Checkbox()
        self.label = ft.Text(value=self.text)
        self.controls = [self.checkbox, self.label]

    def toggle(self, e):
        self.label.color = ft.Colors.GREY if self.checkbox.value else None
        self.update()

Lifecycle Methods

生命周期方法

MethodWhen calledUse for
init()
After
__init__
Setup sub-controls
build()
When assigned
self.page
Platform-dependent logic
did_mount()
After added to pageStart timers, fetch data
will_unmount()
Before removedClean up, cancel tasks
before_update()
Every
update()
Sync derived state
Isolation rule: Any custom control that calls
self.update()
inside its own methods must set
is_isolated = True
(or override
is_isolated
property to return
True
).
方法调用时机用途
init()
__init__
之后
设置子控件
build()
self.page
被赋值时
处理平台相关逻辑
did_mount()
被添加到页面后启动定时器、获取数据
will_unmount()
被移除前清理资源、取消任务
before_update()
每次调用
update()
同步派生状态
隔离规则:任何在自身方法内调用
self.update()
的自定义控件,必须设置
is_isolated = True
(或重写
is_isolated
属性使其返回
True
)。

Navigation and Routing

导航与路由

Use
page.on_route_change
+
page.views
as the single source of truth:
python
def main(page: ft.Page):
    def route_change():
        page.views.clear()
        page.views.append(ft.View("/", controls=[...]))
        if page.route == "/settings":
            page.views.append(ft.View("/settings", controls=[...]))
        page.update()

    async def view_pop(e):
        page.views.remove(e.view)
        await page.push_route(page.views[-1].route)

    page.on_route_change = route_change
    page.on_view_pop = view_pop
    route_change()

ft.run(main)
Navigate:
await page.push_route("/settings")
Parameterized routes:
python
troute = ft.TemplateRoute(page.route)
if troute.match("/items/:id"):
    print(troute.id)
Routing rules:
  • Always keep a root
    /
    view in
    page.views
  • Centralize all route logic in
    page.on_route_change
  • Always handle
    page.on_view_pop
    to stay in sync
使用
page.on_route_change
+
page.views
作为单一数据源:
python
def main(page: ft.Page):
    def route_change():
        page.views.clear()
        page.views.append(ft.View("/", controls=[...]))
        if page.route == "/settings":
            page.views.append(ft.View("/settings", controls=[...]))
        page.update()

    async def view_pop(e):
        page.views.remove(e.view)
        await page.push_route(page.views[-1].route)

    page.on_route_change = route_change
    page.on_view_pop = view_pop
    route_change()

ft.run(main)
导航
await page.push_route("/settings")
参数化路由:
python
troute = ft.TemplateRoute(page.route)
if troute.match("/items/:id"):
    print(troute.id)
路由规则:
  • 始终在
    page.views
    中保留根路径
    /
    的视图
  • 将所有路由逻辑集中在
    page.on_route_change
  • 务必处理
    page.on_view_pop
    以保持同步

Theming

主题配置

python
undefined
python
undefined

App-wide theme

全局应用主题

page.theme = ft.Theme(color_scheme_seed=ft.Colors.GREEN) page.dark_theme = ft.Theme(color_scheme_seed=ft.Colors.BLUE) page.theme_mode = ft.ThemeMode.SYSTEM # LIGHT | DARK | SYSTEM
page.theme = ft.Theme(color_scheme_seed=ft.Colors.GREEN) page.dark_theme = ft.Theme(color_scheme_seed=ft.Colors.BLUE) page.theme_mode = ft.ThemeMode.SYSTEM # LIGHT | DARK | SYSTEM

Nested theme (scoped to a container)

嵌套主题(作用于容器范围)

ft.Container( theme=ft.Theme(color_scheme=ft.ColorScheme(primary=ft.Colors.PINK)), content=ft.Button("Pink button"), )
undefined
ft.Container( theme=ft.Theme(color_scheme=ft.ColorScheme(primary=ft.Colors.PINK)), content=ft.Button("Pink button"), )
undefined

Async Apps

异步应用

Mark
main
async for
asyncio
support. Use
asyncio.sleep()
(not
time.sleep()
).
python
import asyncio
import flet as ft

async def main(page: ft.Page):
    async def on_click(e):
        await asyncio.sleep(1)
        page.add(ft.Text("Done!"))

    page.add(ft.Button("Click me", on_click=on_click))

ft.run(main)
Use
page.run_task(coro)
to run background coroutines from
did_mount()
.
main
标记为异步以支持
asyncio
,使用
asyncio.sleep()
(而非
time.sleep()
)。
python
import asyncio
import flet as ft

async def main(page: ft.Page):
    async def on_click(e):
        await asyncio.sleep(1)
        page.add(ft.Text("Done!"))

    page.add(ft.Button("Click me", on_click=on_click))

ft.run(main)
可在
did_mount()
中使用
page.run_task(coro)
运行后台协程。

Performance: Large Lists

性能优化:大型列表

Use
ListView
or
GridView
instead of
Column
/
Row
for hundreds of items:
python
undefined
当有数百个项目时,使用
ListView
GridView
而非
Column
/
Row
python
undefined

Efficient: renders only visible items

高效:仅渲染可见项

lv = ft.ListView(expand=True, spacing=10, item_extent=50) for i in range(5000): lv.controls.append(ft.Text(f"Line {i}")) page.add(lv)
lv = ft.ListView(expand=True, spacing=10, item_extent=50) for i in range(5000): lv.controls.append(ft.Text(f"Line {i}")) page.add(lv)

Batch updates to avoid large WebSocket messages

批量更新以避免过大的WebSocket消息

for i in range(5000): lv.controls.append(ft.Text(f"Line {i}")) if i % 500 == 0: page.update() page.update()
undefined
for i in range(5000): lv.controls.append(ft.Text(f"Line {i}")) if i % 500 == 0: page.update() page.update()
undefined

Implicit Animations

隐式动画

Enable by setting
animate_*
properties on controls:
python
undefined
通过设置控件的
animate_*
属性启用:
python
undefined

Opacity fade

透明度淡入淡出

container = ft.Container( width=150, height=150, bgcolor=ft.Colors.BLUE, animate_opacity=300, # ms )
container = ft.Container( width=150, height=150, bgcolor=ft.Colors.BLUE, animate_opacity=300, # 毫秒 )

Scale with bounce curve

带弹跳曲线的缩放动画

ft.Container( animate_scale=ft.Animation( duration=600, curve=ft.AnimationCurve.BOUNCE_OUT, ) )
ft.Container( animate_scale=ft.Animation( duration=600, curve=ft.AnimationCurve.BOUNCE_OUT, ) )

Position animation (inside Stack or page.overlay)

位置动画(在Stack或page.overlay中使用)

ft.Container(animate_position=1000)
ft.Container(animate_position=1000)

Animated content switcher

动画内容切换器

ft.AnimatedSwitcher( content, transition=ft.AnimatedSwitcherTransition.SCALE, duration=500, )
undefined
ft.AnimatedSwitcher( content, transition=ft.AnimatedSwitcherTransition.SCALE, duration=500, )
undefined

Window Control (Desktop)

窗口控制(桌面端)

python
page.title = "My App"
page.window.width = 800
page.window.height = 600
page.window.resizable = True
page.window.always_on_top = False
page.window.center()
python
page.title = "My App"
page.window.width = 800
page.window.height = 600
page.window.resizable = True
page.window.always_on_top = False
page.window.center()

Quick Reference: Common Controls

快速参考:常用控件

python
ft.Text("Hello", size=20, weight=ft.FontWeight.BOLD)
ft.Button("Click", on_click=handler)
ft.IconButton(ft.Icons.ADD, on_click=handler)
ft.TextField(label="Name", on_change=handler)
ft.Checkbox(label="Check me", on_change=handler)
ft.Dropdown(options=[ft.dropdown.Option("A"), ft.dropdown.Option("B")])
ft.Image(src="photo.jpg")                   # from assets/
ft.Image(src="https://example.com/img.png") # remote
ft.AppBar(title=ft.Text("Title"))
ft.NavigationDrawer(controls=[...])
ft.AlertDialog(title=ft.Text("Alert"), content=ft.Text("Body"))
python
ft.Text("Hello", size=20, weight=ft.FontWeight.BOLD)
ft.Button("Click", on_click=handler)
ft.IconButton(ft.Icons.ADD, on_click=handler)
ft.TextField(label="Name", on_change=handler)
ft.Checkbox(label="Check me", on_change=handler)
ft.Dropdown(options=[ft.dropdown.Option("A"), ft.dropdown.Option("B")])
ft.Image(src="photo.jpg")                   # 来自assets/目录
ft.Image(src="https://example.com/img.png") # 远程图片
ft.AppBar(title=ft.Text("Title"))
ft.NavigationDrawer(controls=[...])
ft.AlertDialog(title=ft.Text("Alert"), content=ft.Text("Body"))

Additional Resources

额外资源

Reference Files

参考文档

  • references/controls-and-layout.md
    - Complete layout patterns, Container styling, Stack positioning, and control properties
  • references/patterns-and-best-practices.md
    - State management, session/client storage, PubSub, keyboard shortcuts, error handling
  • references/controls-and-layout.md
    - 完整的布局模式、Container样式、Stack定位及控件属性说明
  • references/patterns-and-best-practices.md
    - 状态管理、会话/客户端存储、发布订阅、键盘快捷键、错误处理

Example Files

示例代码

  • examples/counter-app.py
    - Minimal working counter demonstrating page setup and event handlers
  • examples/custom-control.py
    - Composite custom control with lifecycle methods and isolation
  • examples/counter-app.py
    - 极简计数器应用,演示页面设置与事件处理
  • examples/custom-control.py
    - 带生命周期方法与隔离属性的复合自定义控件