跳到主要内容

画布

· 阅读需 4 分钟
Feodor Fitsner
Flet 创始人兼开发者

释放你内心的艺术家🧑‍🎨,并通过全新的 Canvas 控件在 Flet 0.6.0 中增强你的 Flet 创造力!

Canvas 允许你使用一组基本几何图形("形状")(如线条、圆、弧线、路径和文本)绘制任意图形。我敢打赌,你甚至可以使用 Canvas 控件实现你自己的图表

将 Canvas 和 GestureDetector 结合使用,你就能得到一个自由绘画的应用程序 - Flet Brush 😀!

示例源代码

Canvas 控件位于 flet.canvas 包中。你需要另一个导入语句来使用它:

import flet.canvas as cv

下面是一个简单的程序,使用填充和描边 Paint,使用 CircleArc 形状绘制一个笑脸:

import math
import flet as ft
import flet.canvas as cv

def main(page: ft.Page):
stroke_paint = paint = ft.Paint(stroke_width=2, style=ft.PaintingStyle.STROKE)
fill_paint = paint = ft.Paint(style=ft.PaintingStyle.FILL)
cp = cv.Canvas(
[
cv.Circle(100, 100, 50, stroke_paint),
cv.Circle(80, 90, 10, stroke_paint),
cv.Circle(84, 87, 5, fill_paint),
cv.Circle(120, 90, 10, stroke_paint),
cv.Circle(124, 87, 5, fill_paint),
cv.Arc(70, 95, 60, 40, 0, math.pi, paint=stroke_paint),
],
width=float("inf"),
expand=True,
)

page.add(cp)

ft.app(main)

文档中阅读更多关于 Canvas 的内容,并探索 Canvas 示例

其他更新

富文本支持

在处理 Canvas 上的文字绘制时,作为本次发布的附加功能,我们实现了一个新的 TextSpan 控件,现在可以与 Text.spans 结合使用输出富文本。

查看富文本示例:

按钮的 url 属性

如果你需要通过点击按钮或任何其他带有 on_click 事件的控件打开一个 URL,你可以直接在 url 中提供该 URL,而无需在代码中使用 page.launch_url() 方法。

不再需要这样:

ft.ElevatedButton("前往谷歌", on_click=lambda e: e.page.launch_url("https://www.google.com"))

只需要这样:

ft.ElevatedButton("前往谷歌", url="https://www.google.com")

新的 url 属性还解决了 Safari 上阻止弹窗的问题

Markdown 中的自动链接跟随

作为 url 属性的延续,Markdown 控件现在可以启用自动跟随文档中的链接:

import flet as ft

md = """
[前往谷歌](https://www.google.com)
"""

def main(page: ft.Page):
page.add(
ft.Markdown(
md,
extension_set=ft.MarkdownExtensionSet.GITHUB_WEB,
auto_follow_links=True,
)
)

ft.app(main)

更好的 Web 支持

在这个版本中,我们还对Web支持进行了一些改进,例如在page.client_idpage.client_user_agent中捕获用户信息,同时修复了与路由相关的严重的#1333#1289错误。

今天就介绍到这里!

将Flet模块升级到最新版本(pip install flet --upgrade),试用一下画布和富文本,并让我们知道你的想法!

Flet图表

· 阅读需 3 分钟
Feodor Fitsner
Flet创始人和开发人员

去年我们介绍了对Matplotlib和Plotly图表的支持。这两个库都可以将图表导出为SVG图像,然后在Flet应用中显示。然而,这种图表虽然满足了可视化的目的,但缺少交互性和动画效果。

今天,我们发布了版本0.5.2的Flet,其中内置了基于优秀的fl_chart库的图表控件📊!

我们引入了三个新的图表控件:

折线图(LineChart)

文档 · 示例

条形图(BarChart)

文档 · 示例

饼图(PieChart)

文档 · 示例

备注

我们花了很多时间研究fl_chart库,试图在Flet中以Flet的方式实现它的大部分功能。然而,如果您在Flet中看到任何遗漏的功能,但库中有,请提交一个新的功能请求

其他变更

Pyodide 0.23

Pyodide是一个在浏览器中提供Python运行时的工具,用于将Flet应用作为静态网站运行。它已经升级到0.23版本,该版本基于Python 3.11.2,并且带来了一些大小和性能改进

内存泄漏修复

在这个版本中,我们非常关注Flet应用中的内存泄漏问题。现在,当用户关闭会话时,其内存将被可靠地释放和垃圾回收。这使得Flet适用于具有大量用户的生产应用程序。

将Flet模块升级到最新版本(pip install flet --upgrade),尝试使用图表,并告诉我们您的想法(https://discord.gg/dK42zqUs)!

嘿,Flet项目已经获得了⭐️ 5K星⭐️ - 感谢大家的持续支持!

使用Pyodide创建独立的Flet Web应用

· 阅读需 6 分钟
Feodor Fitsner
Flet 创始人和开发者

我们刚刚发布了 Flet 0.4.0,新增了一个非常令人兴奋的功能 - 将Flet应用打包成独立的静态网站,可以完全在浏览器中运行!这个应用可以发布到任何支持静态网站的免费主机,比如GitHub Pages或Cloudflare Pages。这得益于 Pyodide - 一个用于WebAssembly的Python移植工具!

您可以快速使用Python构建出色的单页应用程序(SPA),并在任何地方进行托管!无需HTML、CSS或JavaScript!

快速示例:使用Pyodide创建Flet应用

安装最新的Flet包:

pip install flet --upgrade

创建一个简单的 counter.py 应用:

counter.py
import flet as ft

def main(page: ft.Page):
page.title = "Flet计数器示例"
page.vertical_alignment = ft.MainAxisAlignment.CENTER

txt_number = ft.TextField(value="0", text_align=ft.TextAlign.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(
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(main)

运行全新的 flet publish 命令将Flet应用发布为静态网站:

flet publish counter.py

网站将发布到与 counter.py 同级的 dist 目录中。 使用内置的Python Web服务器进行测试:

python -m http.server --directory dist

在浏览器中打开 http://localhost:8000 来查看发布的应用。

以下是一些托管在Cloudflare Pages上的实例 Flet 应用:

了解更多关于将Flet应用发布为独立网站的详细信息,请查看我们的指南

Python中的内置Fletd服务器

Flet 0.4.0 还实现了 新的Flet桌面架构

它用一个轻量级的Python代码替换了Go编写的Fletd服务器,带来了如下优点:

  1. 运行Flet应用只需要2个系统进程:Python解释器和Flutter客户端。
  2. 通信开销更小(去掉了Python和Fletd之间的两次网络跳转),延迟更低(Windows上使用TCP,macOS/Linux上使用Unix域套接字)。
  3. 默认情况下,在Windows上,Shim绑定到127.0.0.1,这更安全。
  4. flet pack生成的独立应用程序包的大小减小了约8 MB。

此外,该实现还需要支持Pyodide(我们无法在浏览器中运行Go Web服务器,对吧?)并为iOS和Android支持铺平了道路。

其他变化

  • 所有从Web URL加载资源的控件(Image.srcAudio.srcPage.fontsContainer.image_src)现在也能够从本地文件中加载资源,只需在文件系统中提供完整路径,或者在assets目录中提供相对路径。对于桌面应用程序,src属性中的路径可以是以下之一:
    • 相对于assets目录的路径,带或不带斜杠,例如:/image.pngimage.png。不应包含构件目录的名称。
    • 计算机文件系统中的绝对路径,例如:C:\projects\app\assets\image.png/Users/john/images/picture.png
    • 完整的URL,例如:https://mysite.com/images/pic.png
    • 添加page.on_error = lambda e: print("Page error:", e.data)以查看加载失败的图像。
  • flet Python包已分为两个包:flet-coreflet
  • 用Poetry替换了PDM。
  • 所有地方都移除了beartype

💥 破坏性变更

  • 默认路由方案从“hash”改为“path”(在应用程序URL末尾没有/#/)。使用ft.app(main, route_url_strategy="hash")以获得原始行为。
  • 独立桌面Flet应用程序不再支持OAuth身份验证。

异步支持

Flet应用程序现在可以编写为异步应用程序,并且可以使用asyncio和其他Python异步库。在Flet中,调用协程是自然支持的,因此您无需包装它们以进行同步运行。

要从异步Flet应用程序开始,应将main()方法设置为async

import flet as ft

async def main(page: ft.Page):
await page.add_async(ft.Text("Hello, async world!"))

ft.app(main)

阅读指南了解有关编写异步Flet应用程序的更多信息。

结论

Flet 0.4.0 带来了以下令人激动的功能:

  • 在浏览器中运行Pyodide的独立Web应用程序,并在廉价托管服务上托管。
  • 更快、更安全的体系结构,内置Fletd服务器。
  • 对异步应用程序的支持。

将Flet模块升级到最新版本(pip install flet --upgrade),尝试使用flet publish命令,并告诉我们您的想法!

顺便说一下,Flet项目已经获得了⭐️ 4.2K颗星星 ⭐️(仅一个月内增加了1K) - 继续加油!

使用自定义图标打包桌面应用程序

· 阅读需 2 分钟
Feodor Fitsner
Flet 创始人和开发者

新年快乐!Flet项目在 GitHub 上获得了⭐️ 3.3K颗星星 ⭐️,这非常令人兴奋和鼓舞人心!感谢大家的支持!

我们在新年伊始发布了Flet 0.3.2,带来了一个期待已久的功能:使用自定义图标创建独立的桌面应用程序包!

flet命令一直被用来运行具有热重新加载功能的 Flet 程序,但最近我们重新设计了 Flet CLI 来支持多个操作。

现在有了一个新的 flet pack 命令,它封装了 PyInstaller 的API,可以将你的 Flet Python 应用程序打包成一个独立的 Windows 可执行文件或 macOS 应用程序包,用户可以在没有安装 Python 的情况下运行。

命令的 --icon 参数现在不仅可以更改可执行文件的图标,还可以更改 Flet 应用程序窗口的图标以及在 macOS 的 Dock 中显示的图标、Windows 任务栏中显示的图标、macOS 的 "关于" 对话框中显示的图标、任务管理器和活动监视器中显示的图标:

还可以更改包名称、版本和版权信息:

请在更新的指南中查找所有可用的打包桌面应用程序的选项。

Upgrade Flet module to the latest version (pip install flet --upgrade), give flet pack command a try and let us know what you think!

Flet 移动更新

· 阅读需 8 分钟
Feodor Fitsner
Flet 创始人和开发者

这篇文章是几个月前发布的 Flet 移动战略 的续篇。

我们最初在移动设备上运行 Flet 的方法是使用 Server-Driven UI(SDUI)。尽管 SDUI 有其自身的优点(如绕过应用商店进行应用更新),但它并不适用于所有情况,需要 Web 服务器托管 Python 部分的应用程序,并且由此增加了响应延迟,这对于需要几乎即时 UI 响应的用户操作(如绘图应用程序)并不理想。

我一直在思考如何将 Python 运行时嵌入到 Flutter iOS 或 Android 应用程序中以运行用户的 Python 程序。毫无疑问,从技术上讲是可行的,因为 Kivy 和 BeeWare 项目已经实现了这一点。

当前的 Flet 架构

当前 Flet 桌面应用程序的架构如下图所示:

Flet 桌面应用程序架构图

在桌面上运行 Flet 程序涉及到三个应用程序(进程)协同工作:

  • Python 运行时 (python3) - 运行您的 Python 脚本的 Python 解释器。这是您从命令行启动的内容。Python 启动 Fletd 服务器并通过 WebSockets 连接到它。
  • Fletd 服务器 (fletd) - 使用 Go 编写的 Flet Web 服务器,监听一个 TCP 端口。Fletd 保存所有用户会话的状态(对于桌面应用程序只有一个会话),并在 Python 程序和 Flet 客户端之间分发页面更新和用户生成的事件。
  • Flet 客户端 (flet) - 使用 Flutter 编写的桌面应用程序,在本地操作系统窗口中显示 UI。Flet 客户端通过 WebSockets 连接到 Fletd 服务器。

上述架构对于 Flet Web 应用程序效果良好,因为 Web 服务器是必要的一部分,但对于桌面应用程序来说似乎是多余的:

  • 如果所有三个进程在同一台计算机上运行,WebSockets 可以用消息传递队列或命名管道替代,减少开销。
  • 对于只有一个用户会话且 UI 状态永久存储在 Flet 桌面客户端中且从不“重新加载”的桌面应用程序来说,Fletd 服务器没有多大意义。

新的 Flet 桌面架构

通过将 Fletd 替换为用 Python 编写的“存根”,并通过 sockets(Windows)和 named pipes(macOS 和 Linux)与 Flet 桌面客户端通信,可以简化 Flet 桌面应用程序的架构:

新的 Flet 桌面应用程序架构图

Flet 移动架构

移动应用程序在一个非常严格的环境中运行,具有许多限制。例如,在 iOS 上,应用程序不能生成新进程。换句话说,Flet Flutter 应用程序不能只是启动 "python.exe" 并将您的脚本作为参数传递。

幸运的是,Python 可以被嵌入到另一个应用程序中作为 C 库,而 Dart(Flutter 应用程序使用的语言)允许通过 FFI(Foreign Function Interface)调用 C 库。

此外,尽管 Android 允许加载动态链接库,但 iOS 要求所有库静态链接到应用程序可执行文件中。如果您有兴趣,这篇文章更详细地介绍了 Dart FFI。

Flet 移动架构可能如下所示:

Flet 移动应用程序架构图

Python 运行时将与 Flutter 客户端应用程序静态或动态链接,并通过 FFI 和/或命名管道进行调用。

尽管在移动设备上运行 Python 存在一些限制。最重要的限制之一是要求使用适用于移动设备 ARM64 架构的“纯” Python 模块或使用专门为移动设备编译的具有本机代码的模块。

异步支持

Asyncio是Python 3的一部分,我们开始看到越来越多的库与异步/等待编程模型一起使用,这对于I/O密集型和UI逻辑更高效。

目前,Flet在新线程中生成所有UI事件处理程序,而且随处可见threading.sleep()调用阻塞线程,仅仅是为了进行一些UI动画。所有这些看起来都很费资源。

在同步代码中使用异步库是可能的,但看起来有些黑客式和低效,因为它会让CPU保持繁忙,只是为了等待异步方法完成。因此,我们希望Flet应用能够对异步代码进行一流的支持。

异步/等待模型是在单个线程中切换任务的状态机。通过使用异步,Flet将能够利用来进行套接字服务器,并使用异步WebSockets库。在单个Flet应用程序中可以同时使用同步和异步事件处理程序,而无需进行任何妥协或黑客。

更令人兴奋的是,异步的Flet将能够完全在浏览器中运行,使用基于WebAssembly(WASM)的Pyodide - 基于WebAssembly(WASM)的Python发行版。WebAssembly尚未支持多线程,因此在单个线程中运行是必须的。想象一下,具有真正离线Flet PWA的Flet Web应用程序,它不需要Web服务器来运行Python代码!

开发计划

我们将在几个迭代中压缩上面的范围:

  1. 支持异步API,并使用异步WebSockets库。与Go中的相同Fletd一起工作。
  2. 使用Python的Fletd服务器("存根")与桌面应用程序一起使用。
  3. 将Python与Fletd“存根”和用户程序嵌入iOS中。
  4. 将Python嵌入Android中。
  5. 为iOS和Android打包移动应用程序。
寻求帮助

🙏 我正在寻找社区中开发Flutter和Python在iOS和Android上的C/C++/本地代码集成部分的帮助。这可以是免费帮助或有偿工作 - 如果你有兴趣,请让我知道!

我们期待与你在Discord(https://discord.gg/dzWXP8SHG8) 频道见面,并积极参与讨论、提供帮助和提问问题!