跳到主要内容

拖放

Flet 中的拖放机制非常简单 - 用户开始拖动 Draggable 控件,然后将其“放置”在 DragTarget 上。如果 draggable 和 drag target 具有相同的 group,则 drag target 将调用 on_accept 事件处理程序,并将 draggable 控件 ID 作为事件数据传递。在这种情况下,draggable serves 作为拖放操作的源“数据”。

让我们看一下以下示例。在下面的程序中,您可以将左侧控件(显示“1”)拖放到右侧控件(显示“0”)上,并在拖放操作完成后,左侧控件将被替换为“0”,右侧控件将变为“1”:

import flet as ft

def main(page: ft.Page):
page.title = "拖放示例"

def drag_accept(e):
# 获取 draggable(源)控件 by its ID
src = page.get_control(e.src_id)
# 更新 draggable 控件中的文本
src.content.content.value = "0"
# 更新 drag target 控件中的文本
e.control.content.content.value = "1"
page.update()

page.add(
ft.Row(
[
ft.Draggable(
group="number",
content=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.CYAN_200,
border_radius=5,
content=ft.Text("1", size=20),
alignment=ft.alignment.center,
),
),
ft.Container(width=100),
ft.DragTarget(
group="number",
content=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.PINK_200,
border_radius=5,
content=ft.Text("0", size=20),
alignment=ft.alignment.center,
),
on_accept=drag_accept,
),
]
)
)

ft.app(target=main)

因此,开发者的责任是确定何时发生 on_accept 事件时,source(draggable)和 destination(drag target)控件将发生什么变化。

尝试一下

将 DragTarget 的 group 属性更改为 number1,注意 on_accept 不再被调用当您将“1”拖放到目标上。

还有其他属性和事件处理程序可以使拖放操作更加交互。例如,draggable 有 content_when_dragging 属性,以便在拖放操作期间显示不同的控件,而不是 content。还有 content_feedback 属性,以便在指针下显示不同的控件。默认情况下,在拖放操作期间,同样的 content 控件将以 50% 不透明度显示在光标下。

让我们修改示例中的 Draggable,以便在拖放操作期间显示一个“孔”而不是拖放控件,并在指针下显示“1”:

...
ft.Draggable(
group="number",
content=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.CYAN_200,
border_radius=5,
content=ft.Text("1", size=20),
alignment=ft.alignment.center,
),
content_when_dragging=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.BLUE_GREY_200,
border_radius=5,
),
content_feedback=ft.Text("1"),
),
...

Drag target 控件还具有 on_will_accepton_leave 事件处理程序,这些处理程序可以帮助更好地可视化何时可以将内容“放置”在目标上。让我们修改示例中的 DragTarget,以便在目标准备好接受拖放操作时绘制一个边框:

import flet as ft

def main(page: ft.Page):
page.title = "拖放示例 2"

def drag_accept(e):
# 获取 draggable(源)控件 by its ID
src = page.get_control(e.src_id)
# 更新 draggable 控件中的文本
src.content.content.value = "0"
# 重置源组,以便它不能再被拖放到目标上
src.group = ""
# 更新 drag target 控件中的文本
e.control.content.content.value = "1"
# 重置边框
e.control.content.border = None
page.update()

def drag_will_accept(e):
# 黑色边框 when it's allowed to drop and red when it's not
e.control.content.border = ft.border.all(
2, ft.colors.BLACK45 if e.data == "true" else ft.colors.RED
)
e.control.update()

def drag_leave(e):
e.control.content.border = None
e.control.update()

page.add(
ft.Row(
[
ft.Draggable(
group="number",
content=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.CYAN_200,
border_radius=5,
content=ft.Text("1", size=20),
alignment=ft.alignment.center,
),
content_when_dragging=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.BLUE_GREY_200,
border_radius=5,
),
content_feedback=ft.Text("1"),
),
ft.Container(width=100),
ft.DragTarget(
group="number",
content=ft.Container(
width=50,
height=50,
bgcolor=ft.colors.PINK_200,
border_radius=5,
content=ft.Text("0", size=20),
alignment=ft.alignment.center,
),
on_accept=drag_accept,
on_will_accept=drag_will_accept,
on_leave=drag_leave,
),
]
)
)

ft.app(target=main)