控件引用
Flet控件是对象,为了访问它们的属性,我们需要保留对这些对象的引用(变量)。
考虑以下示例:
import flet as ft
def main(page):
first_name = ft.TextField(label="First name", autofocus=True)
last_name = ft.TextField(label="Last name")
greetings = ft.Column()
def btn_click(e):
greetings.controls.append(ft.Text(f"Hello, {first_name.value} {last_name.value}!"))
first_name.value = ""
last_name.value = ""
page.update()
first_name.focus()
page.add(
first_name,
last_name,
ft.ElevatedButton("Say hello!", on_click=btn_click),
greetings,
)
ft.app(target=main)
在main()
方法的开头,我们创建了三个控件,这些控件将在按钮的on_click
处理程序中使用:两个TextField
用于名字和姓氏,以及一个Column
作为问候消息的容器。我们使用所有属性设置来创建控件,并在main()
方法的末尾,在page.add()
调用中使用它们的引用(变量)。
当添加了更多的控件和事件处理程序时,将所有控件定义放在一个地方变得具有挑战性,它们会分散在main()
主体中。只看一眼page.add()
的参数,很难想象(不用不断跳转到IDE中的变量定义)最终的表单会是什么样子的。
page.add(
first_name,
last_name,
ft.ElevatedButton("Say hello!", on_click=btn_click),
greetings,
)
first_name
是一个TextField,它有设置自动聚焦(autofocus)吗?greetings是一个Row还是一个Column?
Ref
类
Flet提供了Ref
实用类,允许定义对控件的引用,可以在事件处理程序中使用该引用,并在构建树时将引用设置为实际控件。这个想法来自于React。
要定义一个新的带类型的控件引用:
first_name = ft.Ref[ft.TextField]()
要访问引用的控件(解引用控件),使用Ref.current
属性:
# 清空名字
first_name.current.value = ""
要将控件分配给引用,请将Control.ref
属性设置为引用:
page.add(
ft.TextField(ref=first_name, label="First name", autofocus=True)
)
所有Flet控件都有ref
属性。
我们可以重写我们的程序来使用引用:
import flet as ft
def main(page):
first_name = ft.Ref[ft.TextField]()
last_name = ft.Ref[ft.TextField]()
greetings = ft.Ref[ft.Column]()
def btn_click(e):
greetings.current.controls.append(
ft.Text(f"Hello, {first_name.current.value} {last_name.current.value}!")
)
first_name.current.value = ""
last_name.current.value = ""
page.update()
first_name.current.focus()
page.add(
ft.TextField(ref=first_name, label="First name", autofocus=True),
ft.TextField(ref=last_name, label="Last name"),
ft.ElevatedButton("Say hello!", on_click=btn_click),
ft.Column(ref=greetings),
)
ft.app(target=main)
现在我们可以清楚地看到page.add()
中页面的结构和所构建的所有控件。
是的,逻辑变得有点冗长,因为你需要添加.current.
来访问ref的控件,但这只是个人偏好的问题 :)