Flet 快速上手
Flet 是什么?
Flet 是一个 UI 框架,允许你使用 Python 来构建 Web、桌面端和移动端应用。
构建第一个 Flet 应用
下面将构建我们的第一个 Flet 应用,该应用只有一个简单的计数功能。
首先我们需要执行命令 pip install flet
来安装 flet。然后我们创建一个 counter.py
文件用于实现我们的计数 app。在 counter.py 中加上如下代码:
import flet
from flet import IconButton, Page, Row, TextField, icons
def main(page: Page):
page.title = "Flet counter example"
page.vertical_alignment = "center"
txt_number = TextField(value="0", text_align="right", width=100)
def minus_click(e):
txt_number.value = str(int(txt_number.value) - 1)
page.update()
def plus_click(e):
txt_number.value = str(int(txt_number.value) + 1)
page.update()
page.add(
Row(
[
IconButton(icons.REMOVE, on_click=minus_click),
txt_number,
IconButton(icons.ADD, on_click=plus_click),
],
alignment="center",
)
)
flet.app(target=main)
接下来只需要使用命令 python counter.py
即可运行我们的第一个 flet 应用了。
在实际开发中使用 flet create <project-name>
来创建一个 flet 项目,使用 flet run
来运行 flet 项目。
基本概念
Controls
用户界面在 Flet 中是由一个一个的 control 组成的,control 只能在 control 内,其中 Page
是最顶级的 control,也就是说用户看到的界面其实是一棵 control 树。下述代码就是将一个 Text
control 加入到 Page
内,然后调用 update 来更新界面:
import flet as ft
def main(page: ft.Page):
t = ft.Text(value="Hello, world!", color="green")
page.controls.append(t)
page.update()
ft.app(target=main)
上述代码中 Text
就是 Flet 提供的 control,我们也可以自定义 control 来灵活实现需求:
class MyButton(ft.ElevatedButton):
def __init__(self, text):
super().__init__()
self.bgcolor = ft.colors.ORANGE_300
self.color = ft.colors.GREEN_800
self.text = text
在自定义的 ByButton
中会继承 Flet 的 ElevatedButton
control 然后修改其字体和背景色。
control 还提供了一些钩子函数:
-
build
:创建 control 时调用 -
did_mount
:control 被挂载后调用 -
will_unmount
:移除 control 后调用 -
before_update
:更新 control 前调用
Adaptive apps
Flet 框架提供了多平台自适应功能,此功能默认为关闭状态,将 page.adaptive
设置为 True
将开启自适应功能。开启自适应功能后一些 controls 在 IOS 和其它平台中显示样式会不一样。Flet 提供的自适应 control 请阅读文档:Material and Cupertino controls。
除此之外我们可以自定义 control 来实现多平台适配。在自定义 control 中检查 self.page.platform
来区分程序当前运行的平台:
class AdaptiveNavigationBarDestination(ft.NavigationBarDestination):
def __init__(self, ios_icon, android_icon, label):
super().__init__()
self._ios_icon = ios_icon
self._android_icon = android_icon
self.label = label
def build(self):
# we can check for platform in build method because self.page is known
self.icon = (
self._ios_icon
if self.page.platform == ft.PagePlatform.IOS
or self.page.platform == ft.PagePlatform.MACOS
else self._android_icon
)
Navigation and routing
Flet 提供了路由功能。Flet 提供了两种路由模式:
-
Path:普通路由,如:
/post/1
-
Hash:哈希路由,如:
/#/post/1
我们可以通过page.route
属性来获取当前页面的路由同时也能修改此熟悉从而实现跳转路由的功能。Flet 还提供了 page.on_route_change
来监听路由变化。使用 page.on_view_pop
可以获取上一个页面试图。
import flet as ft
def main(page: ft.Page):
page.add(ft.Text(f"Initial route: {page.route}"))
def route_change(e: ft.RouteChangeEvent):
page.add(ft.Text(f"New route: {e.route}"))
def go_store(e):
page.route = "/store"
page.update()
page.on_route_change = route_change
page.add(ft.ElevatedButton("Go to Store", on_click=go_store))
ft.app(target=main, view=ft.AppView.WEB_BROWSER)
打包 Flet 项目
Flet 打包程序提供了两种方法
-
flet pack main.py
:这是旧的打包 flet 程序命令,依赖 pyinstaller。注意:这种方法方法打包优点是较为简单,缺点是打包出的程序性能较差(简单 demo 打包后打开时间要七秒左右,使用 flet build 打包仅一秒多即可打开) -
flet build macos
:这是新打包命令,依赖 Flutter。
Flet pack demo
下述示例是基于 MacOS 14 m2 芯片构建
使用 flet pack
命令打包程序前需要先使用 pip install pyinstaller
命令来安装 pyinstaller 依赖。然后执行 flet pack main.py
即可打包程序。 命令详情参考文档:packaging-desktop-app
Flet build demo
下述示例是基于 MacOS 14 m2 芯片构建
环境准备
-
网络环境:打包构建过程中会使用到一些外网依赖故需要提前配置网络代理,配置方法可参考命令
export http_proxy=http://127.0.0.1:1087;export https_proxy=http://127.0.0.1:1087
对应端口为本机实际代理端口。 -
Flutter 环境:由于 Flet 打包构建实际是使用 Fletter,故我们需要配置 Flutter 环境。
-
下载安装 Flutter SDK:install-the-flutter-sdk 打开链接后选择 Download and install 中 arm 版本压缩包下载解压。然后如下环境变量:
-
export PUB_HOSTED_URL=https://pub.flutter-io.cn
-
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
-
export PATH="{flutter sdk 安装目录}/bin:$PATH"
-
-
打开 AppStore 商店安装 Xcode,用于编译 Swift,安装过程可能会让你升级操作系统。
-
安装 CocoaPods 用于编译 Flutter,CocoaPods 其作用为管理依赖。
-
打包
使用名flet build <target_platform>
即可打包 Flet 项目,具体打包命令参考文档:how-it-works
Github Action demo
由于 flet pack 打包性能较差,故 github action 打包构建将使用 flet build 方式进行。
name: Test build
on:
release:
types: [ created ]
# Allows you to run this workflow manually from the Actions tab of the repository
workflow_dispatch:
# flet build macos --verbose --build-number=1 --build-version=1.0.0
env:
PYTHON_VERSION: 3.11.9
FLUTTER_VERSION: 3.24.0
jobs:
build-macos:
strategy:
matrix:
os: [macos-14] # 定义多个 macOS 版本,macos-14是m1芯片即arm64
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Python Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Setup Flutter ${{ env.FLUTTER_VERSION }}
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Flet Build macOS
run: |
flutter config --no-analytics
flet build macos --verbose
- name: Package .app folder
run: |
cd build/macos
tar -czf test.tar.gz test.app
cd ../
cd ../
mkdir dist
cp build/macos/test.tar.gz dist/test.tar.gz
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./dist/test.tar.gz
asset_name: test-${{ matrix.os }}.tar.gz
asset_content_type: application/octet-stream