python-flet
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePython 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 function receiving a and ends with :
mainft.Pageft.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.pyRun web:
flet run --web main.pyHot reload (watch directory recursively):
flet run --recursive main.py每个Flet应用都有一个接收参数的函数,并以结束:
ft.Pagemainft.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.pyProject Structure
项目结构
my-app/
├── pyproject.toml
└── src/
├── assets/
│ └── icon.png
└── main.pyCreate via: (or )
flet createuv run flet createmy-app/
├── pyproject.toml
└── src/
├── assets/
│ └── icon.png
└── main.py创建方式:(或)
flet createuv run flet createCore Concepts
核心概念
Page
页面
ft.Pagepython
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.AUTOft.Pagepython
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.AUTOControls and update()
update()控件与update()
方法
update()Controls are Python objects. Mutations require or :
page.update()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 pageRule: Prefer over — sends a smaller diff.
control.update()page.update()控件是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
布局控件
| Control | Purpose |
|---|---|
| Vertical stack |
| Horizontal stack |
| Absolute positioning |
| Box with padding, color, border, animation |
| Efficient vertical/horizontal scrollable list |
| Efficient scrollable grid |
python
page.add(
ft.Row(
controls=[ft.Text("Left"), ft.Text("Right")],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
)
)Expand: Use to fill available space:
expand=Truepython
ft.ListView(expand=True, spacing=10)| 控件 | 用途 |
|---|---|
| 垂直堆叠布局 |
| 水平堆叠布局 |
| 绝对定位布局 |
| 带内边距、颜色、边框、动画的容器 |
| 高效的垂直/水平滚动列表 |
| 高效的滚动网格 |
python
page.add(
ft.Row(
controls=[ft.Text("Left"), ft.Text("Right")],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
)
)扩展填充:使用填充可用空间:
expand=Truepython
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.WHITEUse or decorator. Field types must be annotated.
@ft.control@dataclasspython
@ft.control
class PrimaryButton(ft.Button):
bgcolor: ft.Colors = ft.Colors.BLUE_700
color: ft.Colors = ft.Colors.WHITE使用或装饰器,字段必须标注类型。
@ft.control@dataclassComposite 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
生命周期方法
| Method | When called | Use for |
|---|---|---|
| After | Setup sub-controls |
| When assigned | Platform-dependent logic |
| After added to page | Start timers, fetch data |
| Before removed | Clean up, cancel tasks |
| Every | Sync derived state |
Isolation rule: Any custom control that calls inside its own methods must set (or override property to return ).
self.update()is_isolated = Trueis_isolatedTrue| 方法 | 调用时机 | 用途 |
|---|---|---|
| | 设置子控件 |
| 当 | 处理平台相关逻辑 |
| 被添加到页面后 | 启动定时器、获取数据 |
| 被移除前 | 清理资源、取消任务 |
| 每次调用 | 同步派生状态 |
隔离规则:任何在自身方法内调用的自定义控件,必须设置(或重写属性使其返回)。
self.update()is_isolated = Trueis_isolatedTrueNavigation and Routing
导航与路由
Use + as the single source of truth:
page.on_route_changepage.viewspython
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 to stay in sync
page.on_view_pop
使用 + 作为单一数据源:
page.on_route_changepage.viewspython
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
undefinedpython
undefinedApp-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"),
)
undefinedft.Container(
theme=ft.Theme(color_scheme=ft.ColorScheme(primary=ft.Colors.PINK)),
content=ft.Button("Pink button"),
)
undefinedAsync Apps
异步应用
Mark async for support. Use (not ).
mainasyncioasyncio.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)Use to run background coroutines from .
page.run_task(coro)did_mount()将标记为异步以支持,使用(而非)。
mainasyncioasyncio.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 or instead of / for hundreds of items:
ListViewGridViewColumnRowpython
undefined当有数百个项目时,使用或而非/:
ListViewGridViewColumnRowpython
undefinedEfficient: 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()
undefinedfor i in range(5000):
lv.controls.append(ft.Text(f"Line {i}"))
if i % 500 == 0:
page.update()
page.update()
undefinedImplicit Animations
隐式动画
Enable by setting properties on controls:
animate_*python
undefined通过设置控件的属性启用:
animate_*python
undefinedOpacity 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,
)
undefinedft.AnimatedSwitcher(
content,
transition=ft.AnimatedSwitcherTransition.SCALE,
duration=500,
)
undefinedWindow 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
参考文档
- - Complete layout patterns, Container styling, Stack positioning, and control properties
references/controls-and-layout.md - - State management, session/client storage, PubSub, keyboard shortcuts, error handling
references/patterns-and-best-practices.md
- - 完整的布局模式、Container样式、Stack定位及控件属性说明
references/controls-and-layout.md - - 状态管理、会话/客户端存储、发布订阅、键盘快捷键、错误处理
references/patterns-and-best-practices.md
Example Files
示例代码
- - Minimal working counter demonstrating page setup and event handlers
examples/counter-app.py - - Composite custom control with lifecycle methods and isolation
examples/custom-control.py
- - 极简计数器应用,演示页面设置与事件处理
examples/counter-app.py - - 带生命周期方法与隔离属性的复合自定义控件
examples/custom-control.py