跳到主要内容

用户控件

用户控件(UserControl)允许通过组合现有的 Flet 控件来构建隔离的可重用组件。用户控件的行为类似于 Control,可以拥有方法和属性。

以下是一个用户控件的最小示例:

import flet as ft

class GreeterControl(ft.UserControl):
def build(self):
return ft.Text("Hello!")

def main(page):
page.add(GreeterControl())

ft.app(target=main)

UserControl 必须实现 build() 方法,该方法用于构建控件的用户界面,应该返回一个 Control 实例或 List 控件。UserControl 继承自 Stack,因此多个子控件将堆叠在一起显示。如果您需要以不同的方式排列控件的用户界面,请使用 RowColumn 或其他布局控件,例如:

class GreeterControl(ft.UserControl):
def build(self):
return ft.Column([
ft.TextField(label="Your name"),
ft.ElevatedButton("Login")
])

用户控件与外部布局隔离,即当父控件的 update() 方法被调用时,用户控件内部的任何更改都不会包含在更新摘要中。用户控件应该调用 self.update() 将其更改推送到 Flet 页面中,例如:

import flet as ft

class Counter(ft.UserControl):
def add_click(self, e):
self.counter += 1
self.text.value = str(self.counter)
self.update()

def build(self):
self.counter = 0
self.text = ft.Text(str(self.counter))
return ft.Row([self.text, ft.ElevatedButton("Add", on_click=self.add_click)])

def main(page):
page.add(Counter(), Counter())

ft.app(target=main)

您可以将事件处理程序(例如 def add_click(self, e))和控件引用(例如 self.text)声明为类成员,或者在 build() 方法中使用局部变量和内部函数实现用户控件的所有逻辑。例如,上面的代码可以重写为:

class Counter(ft.UserControl):
def build(self):

self.counter = 0
text = ft.Text(str(self.counter))

def add_click(e):
self.counter += 1
text.value = str(self.counter)
self.update()

return ft.Row([text, ft.ElevatedButton("Add", on_click=add_click)])
备注

counter 不能被声明为局部变量,因为它在 add_click 方法中将不可见,因此必须将其声明为类字段 self.counter

用户控件可以具有构造函数以传递自定义数据,例如:

import flet as ft

class Counter(ft.UserControl):
def __init__(self, initial_count):
super().__init__()
self.counter = initial_count

def build(self):
text = ft.Text(str(self.counter))
def add_click(e):
self.counter += 1
text.value = str(self.counter)
self.update()

return ft.Row([text, ft.ElevatedButton("Add", on_click=add_click)])

# 然后使用该控件
def main(page):
page.add(
Counter(100),
Counter(200))

ft.app(target=main)
备注

总是在自己的构造函数中调用 super().__init__()

用户控件提供了生命周期的"钩子"方法:

  • did_mount() - 在将 UserControl 添加到页面并分配临时 id 后调用。
  • will_unmount() - 在将 UserControl 从页面中删除之前调用。

使用这些方法,我们可以实现一个简单的 "倒计时" 控件:

import flet as ft
import time, threading

class Countdown(ft.UserControl):
def __init__(self, seconds):
super().__init__()
self.seconds = seconds

def did_mount(self):
self.running = True
self.th = threading.Thread(target=self.update_timer, args=(), daemon=True)
self.th.start()

def will_unmount(self):
self.running = False

def update_timer(self):
while self.seconds and self.running:
mins, secs = divmod(self.seconds, 60)
self.countdown.value = "{:02d}:{:02d}".format(mins, secs)
self.update()
time.sleep(1)
self.seconds -= 1

def build(self):
self.countdown = ft.Text()
return self.countdown

def main(page: ft.Page):
page.add(Countdown(120), Countdown(60))

ft.app(target=main)