跳到主要内容

控件引用 Control Refs

Flet控件是对象,要访问它们的属性,我们需要保持对这些对象的引用(变量)。

考虑以下示例:

import flet as ft

def main(page):

first_name = ft.TextField(label="名", autofocus=True)
last_name = ft.TextField(label="姓")
greetings = ft.Column()

def btn_click(e):
greetings.controls.append(ft.Text(f"你好,{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("打招呼!", 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 吗?它有设置自动聚焦吗?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="名", 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"你好,{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="名", autofocus=True),
ft.TextField(ref=last_name, label="姓"),
ft.ElevatedButton("打招呼!", on_click=btn_click),
ft.Column(ref=greetings),
)

ft.app(target=main)

现在我们可以清晰地在 page.add() 中看到页面的结构和所有包含的控件。

是的,逻辑变得稍微冗长,因为您需要添加 .current. 来访问引用的控件,但这是个人喜好的问题 :)