跳到主要内容

自定义控件

虽然 Flet 提供了 100 多个内置控件,可以单独使用,但使用 Flet 编程的真正美丽之处在于所有这些控件可以使用 Python 对象oriented 编程概念来创建可重用的 UI 组件。

您可以通过样式化和/或组合现有的 Flet 控件在 Python 中创建自定义控件。

样式控件

您可以创建的最简单的自定义控件是样式控件,例如,具有特定颜色和行为的按钮,该按钮将在应用程序中多次使用。

要创建样式控件,您需要创建一个继承自 Flet 控件的新类,例如 ElevatedButton

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

您的控件具有构造函数,以便自定义属性和事件,并传递自定义数据。请注意,您必须在自己的构造函数中调用 super().__init__(),以便访问 Flet 控件的属性和方法,该控件是您继承的。

现在,您可以在应用程序中使用 MyButton 控件:

import flet as ft

def main(page: ft.Page):
page.add(MyButton(text="OK"), MyButton(text="Cancel"))

ft.app(target=main)

计算器应用教程 中查看使用样式控件的示例。

处理事件

类似于属性,您可以将事件处理程序作为参数传递到自定义控件类构造函数中:

import flet as ft

class MyButton(ft.ElevatedButton):
def __init__(self, text, on_click):
super().__init__()
self.bgcolor = ft.colors.ORANGE_300
self.color = ft.colors.GREEN_800
self.text = text
self.on_click = on_click

def main(page: ft.Page):
def ok_clicked(e):
print("OK clicked")

def cancel_clicked(e):
print("Cancel clicked")

page.add(
MyButton(text="OK", on_click=ok_clicked),
MyButton(text="Cancel", on_click=cancel_clicked),
)

ft.app(target=main)

组合控件

组合自定义控件继承自容器控件,如 ColumnRowStack 或甚至 View,以组合多个 Flet 控件。以下示例是一个 Task 控件,可以在 To-Do 应用程序中使用:

import flet as ft
class Task(ft.Row):
def __init__(self, text):
super().__init__()
self.text_view = ft.Text(text)
self.text_edit = ft.TextField(text, visible=False)
self.edit_button = ft.IconButton(icon=ft.icons.EDIT, on_click=self.edit)
self.save_button = ft.IconButton(
visible=False, icon=ft.icons.SAVE, on_click=self.save
)
self.controls = [
ft.Checkbox(),
self.text_view,
self.text_edit,
self.edit_button,
self.save_button,
]

def edit(self, e):
self.edit_button.visible = False
self.save_button.visible = True
self.text_view.visible = False
self.text_edit.visible = True
self.update()

def save(self, e):
self.edit_button.visible = True
self.save_button.visible = False
self.text_view.visible = True
self.text_edit.visible = False
self.text_view.value = self.text_edit.value
self.update()

def main(page: ft.Page):
page.add(
Task(text="Do laundry"),
Task(text="Cook dinner"),
)


ft.app(target=main)

您可以在 社区示例flet-contrib 存储库中找到更多组合自定义控件的示例。

生命周期方法

自定义控件提供了生命周期“钩子”方法,您可能需要在应用程序中使用这些方法。

build()

build() 方法在控件被创建并分配其 self.page 时被调用。

如果您需要在控件构造函数中执行逻辑,因为它需要访问 self.page,则可以覆盖 build() 方法。例如,选择适合 self.page.platform 的图标,以便为您的自适应应用程序 adaptive app

did_mount()

did_mount() 方法在控件被添加到页面并分配临时 uid 后被调用。

如果您需要在控件被添加到页面后执行逻辑,例如 Weather 小部件,该小部件每分钟调用 Open Weather API 来更新自己以获取最新的天气条件,则可以覆盖 did_mount() 方法。

will_unmount()

will_unmount() 方法在控件被从页面中删除之前被调用。

覆盖 will_unmount() 方法以执行清洁代码。

before_update()

before_update() 方法在控件被更新时被调用。

请确保不要在 before_update() 方法中调用 update() 方法。

隔离控件

自定义控件具有 is_isolated 属性,默认为 False

如果您将 is_isolated 设置为 True,您的控件将从外部布局中隔离,即当调用父控件的 update() 方法时,控件本身将被更新,但控件的子控件的任何更改都不会包含在更新摘要中。隔离控件应该调用 self.update() 将其更改推送到 Flet 页面。

作为最佳实践,任何在其类方法中调用 self.update() 的自定义控件都应该被隔离。

在上面的示例中,简单的样式 MyButton 不需要被隔离,但 Task 应该被隔离:

class Task(ft.Row):
def __init__(self, text):
super().__init__()
self.isolated = True