标签: #Python #Flet #Flutter #跨平台开发 #GUI #移动端开发
🚀 前言:为什么是 Flet?
如果你是 Python 党,你一定会有这样的痛点:
脚本写得很溜,但老板非要个“可视化界面”;或者你想把数据分析结果做成一个手机 App 给客户看。
传统的 Python GUI 库(Tkinter, Qt)在移动端几乎是废的。
Flet 的核心逻辑是:
你负责写 Python(处理数据、逻辑),Flet 负责在后台调用 Flutter 引擎画出漂亮的界面。你不需要懂 CSS 布局,也不需要配置复杂的安卓环境(开发阶段)。
🏗️ 一、 架构原理:Python 怎么指挥 Flutter?
Flet 采用的是 Server-Driven UI (服务端驱动 UI) 模式。
你的 Python 代码其实是一个“服务端”,而显示界面的窗口其实是一个“Flutter 客户端”。
工作流示意图 (Mermaid):
#mermaid-svg-8EU5OcWjU30smwvR{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8EU5OcWjU30smwvR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8EU5OcWjU30smwvR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8EU5OcWjU30smwvR .error-icon{fill:#552222;}#mermaid-svg-8EU5OcWjU30smwvR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8EU5OcWjU30smwvR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8EU5OcWjU30smwvR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8EU5OcWjU30smwvR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8EU5OcWjU30smwvR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8EU5OcWjU30smwvR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8EU5OcWjU30smwvR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8EU5OcWjU30smwvR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8EU5OcWjU30smwvR .marker.cross{stroke:#333333;}#mermaid-svg-8EU5OcWjU30smwvR svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8EU5OcWjU30smwvR p{margin:0;}#mermaid-svg-8EU5OcWjU30smwvR .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8EU5OcWjU30smwvR .cluster-label text{fill:#333;}#mermaid-svg-8EU5OcWjU30smwvR .cluster-label span{color:#333;}#mermaid-svg-8EU5OcWjU30smwvR .cluster-label span p{background-color:transparent;}#mermaid-svg-8EU5OcWjU30smwvR .label text,#mermaid-svg-8EU5OcWjU30smwvR span{fill:#333;color:#333;}#mermaid-svg-8EU5OcWjU30smwvR .node rect,#mermaid-svg-8EU5OcWjU30smwvR .node circle,#mermaid-svg-8EU5OcWjU30smwvR .node ellipse,#mermaid-svg-8EU5OcWjU30smwvR .node polygon,#mermaid-svg-8EU5OcWjU30smwvR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8EU5OcWjU30smwvR .rough-node .label text,#mermaid-svg-8EU5OcWjU30smwvR .node .label text,#mermaid-svg-8EU5OcWjU30smwvR .image-shape .label,#mermaid-svg-8EU5OcWjU30smwvR .icon-shape .label{text-anchor:middle;}#mermaid-svg-8EU5OcWjU30smwvR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8EU5OcWjU30smwvR .rough-node .label,#mermaid-svg-8EU5OcWjU30smwvR .node .label,#mermaid-svg-8EU5OcWjU30smwvR .image-shape .label,#mermaid-svg-8EU5OcWjU30smwvR .icon-shape .label{text-align:center;}#mermaid-svg-8EU5OcWjU30smwvR .node.clickable{cursor:pointer;}#mermaid-svg-8EU5OcWjU30smwvR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8EU5OcWjU30smwvR .arrowheadPath{fill:#333333;}#mermaid-svg-8EU5OcWjU30smwvR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8EU5OcWjU30smwvR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8EU5OcWjU30smwvR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8EU5OcWjU30smwvR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8EU5OcWjU30smwvR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8EU5OcWjU30smwvR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8EU5OcWjU30smwvR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8EU5OcWjU30smwvR .cluster text{fill:#333;}#mermaid-svg-8EU5OcWjU30smwvR .cluster span{color:#333;}#mermaid-svg-8EU5OcWjU30smwvR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8EU5OcWjU30smwvR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8EU5OcWjU30smwvR rect.text{fill:none;stroke-width:0;}#mermaid-svg-8EU5OcWjU30smwvR .icon-shape,#mermaid-svg-8EU5OcWjU30smwvR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8EU5OcWjU30smwvR .icon-shape p,#mermaid-svg-8EU5OcWjU30smwvR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8EU5OcWjU30smwvR .icon-shape rect,#mermaid-svg-8EU5OcWjU30smwvR .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8EU5OcWjU30smwvR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8EU5OcWjU30smwvR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8EU5OcWjU30smwvR :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
UI 端 (Flutter 引擎)
Python 端 (你的代码)
page.add(Text)
WebSocket / HTTP
用户点击事件
更新指令
业务逻辑
Flet Server
Flet Client (App/Web)
这种架构的好处是:极快。Python 修改属性,界面毫秒级刷新,开发体验极佳。
💻 二、 极速上手:写一个计数器 App
安装 Flet:
pip install flet
新建 main.py。你会发现,它的写法非常像 React,但是是 Python 版本的。
import flet as ft
def main(page: ft.Page):
# 1. 设置页面基础属性
page.title = "Flet 计数器"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.theme_mode = ft.ThemeMode.LIGHT # 支持深色/浅色模式切换
# 2. 定义状态变量
txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)
# 3. 定义交互逻辑
def minus_click(e):
txt_number.value = str(int(txt_number.value) – 1)
page.update() # 类似 React 的 setState,通知界面刷新
def plus_click(e):
txt_number.value = str(int(txt_number.value) + 1)
page.update()
# 4. 组装 UI (搭积木)
page.add(
ft.Row(
[
ft.IconButton(ft.icons.REMOVE, on_click=minus_click),
txt_number,
ft.IconButton(ft.icons.ADD, on_click=plus_click),
],
alignment=ft.MainAxisAlignment.CENTER,
)
)
# 运行应用 (默认以桌面应用方式打开)
ft.app(target=main)
运行效果:
你会看到一个原生的 Windows/Mac 窗口,界面是标准的 Material Design 风格,丝滑流畅。
📱 三、 进阶:如何变成手机 App?
Flet 不仅仅是跑在电脑上的。
要在手机上预览,只需要改一行代码:
# view=ft.AppView.WEB_BROWSER 会在浏览器打开
# 局域网预览模式:
ft.app(target=main, port=8550, view=ft.AppView.WEB_BROWSER)
真机调试步骤:
打包 APK (硬核环节)
如果你真的想把这个生成 .apk 文件安装到手机上,Flet 提供了 flet build 命令(基于 Flutter SDK)。
flet build apk
📊 四、 适用场景与避坑
Flet 虽然好用,但不是万能的。
| 应用类型 | 内部工具、管理后台、数据看板、简单的 CRUD 应用 | 3D 游戏、极其复杂的自定义动效、高性能音视频编辑 |
| 开发效率 | ⭐⭐⭐⭐⭐ (极快) | ⭐⭐ |
| 包体积 | 较大 (包含 Python解释器+Flutter引擎) | 小 (原生开发) |
| 生态 | Python 生态 (Pandas, Requests 随便用) | 需要深度调用手机底层硬件 (蓝牙/NFC 支持尚不完善) |
🎯 总结
Flet 是 Python 工程师拓展边界的利器。
它不需要你精通前端,只要你会写 Python 函数,就能构建出颜值得体的跨平台应用。
对于 企业内部工具 或 个人副业项目 来说,Flet 是目前性价比最高的技术选型之一。
Next Step:
把上面的计数器代码复制下来,尝试加一个 ft.Dropdown 下拉框,做一个简单的“汇率转换器”。当你第一次在手机上点开自己写的 App 时,你会爱上这种感觉的。