拖放

Flet 中的拖放机制非常简单——用户开始拖动Draggable控件并将其“拖放”到DragTarget. 如果可拖动和拖动目标相同,则group拖动目标将调用on_accept事件处理程序并将可拖动控件 ID 作为事件数据传递。在这种情况下,draggable 用作拖放操作的源“数据”。

让我们看一下下面的例子。在下面的程序中,您可以在显示“0”的右控件顶部拖动显示“1”的左控件,当拖动操作完成时,左控件被替换为“0”,右控件变为“1”:

import flet
from flet import Container, Draggable, DragTarget, Page, Row, Text, alignment, colors

def main(page: Page):
    page.title = "Drag and Drop example"

    def drag_accept(e):
        # get draggable (source) control by its ID
        src = page.get_control(e.data)
        # update text inside draggable control
        src.content.content.value = "0"
        # update text inside drag target control
        e.control.content.content.value = "1"
        page.update()

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

flet.app(target=main)

因此,开发人员有责任确定事件发生时“源”(可拖动)和“目标”(拖动目标)控件on_accept会发生什么。

尝试一些东西 将 DragTarget 的 group 属性更改为,并且当您在目标上放置“1”时不再调用number1note 。on_accept

还有其他属性和事件处理程序可以使拖放操作更具交互性。例如,draggable 具有content_when_dragging显示不同控件的属性,而不是content在进行拖动操作时。还有content_feedback一个属性可以在指针下显示不同的控件。默认情况下,content拖动时光标下会显示相同的控件,但不透明度为 50%。

让我们在示例中修改 Draggable 以显示一个“洞”来代替拖动的控件,并在拖动时在光标下显示“1”:

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

拖动目标控件还具有事件处理程序on_will_accepton_leave它们有助于更好地可视化何时将某些东西“拖放”到目标上。让我们修改示例中的 DragTarget 以在目标控件准备好接受传入拖动时在目标控件周围绘制边框:

import flet
from flet import (Container, Draggable, DragTarget, Page, Row, Text, alignment, border, colors)

def main(page: Page):
    page.title = "Drag and Drop example 2"

    def drag_accept(e):
        # get draggable (source) control by its ID
        src = page.get_control(e.data)
        # update text inside draggable control
        src.content.content.value = "0"
        # reset source group, so it cannot be dropped to a target anymore
        src.group = ""
        # update text inside drag target control
        e.control.content.content.value = "1"
        # reset border
        e.control.content.border = None
        page.update()

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

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

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

flet.app(target=main)