大型列表

在大多数情况下,您可以使用ColumnRow控件来显示列表,但如果列表包含数百或数千个项目Column,并且Row由于它们会立即呈现所有项目,即使它们在当前滚动位置不可见,也会对滞后的 UI 无效。

在以下示例中,我们将向页面添加 5,000 个文本控件。页面Column用作默认布局容器:

import flet
from flet import Page, Text

def main(page: Page):
    for i in range(5000):
        page.controls.append(Text(f"Line {i}"))
    page.scroll = "always"
    page.update()

flet.app(target=main, view=flet.WEB_BROWSER)

为了显示包含大量项目的列表,使用ListViewGridView控制按需呈现项目,仅在当前滚动位置可见。

ListView可以是垂直的(默认)或水平的。ListView 项在滚动方向上一个接一个地显示。

ListView 已经实现了对其子项的有效按需渲染,但是如果您可以horizontal为所有项目(“范围”)设置相同的固定高度或宽度(对于 ListView),则可以进一步提高滚动性能。这可以通过使用item_extent属性设置绝对范围或通过设置为使所有孩子的范围等于第一个孩子的范围first_item_prototype来完成True

让我们使用 ListView 控件输出一个包含 5,000 个项目的列表:

import flet
from flet import ListView, Page, Text

def main(page: Page):
    lv = ListView(expand=True, spacing=10)
    for i in range(5000):
        lv.controls.append(Text(f"Line {i}"))
    page.add(lv)

flet.app(target=main, view=flet.WEB_BROWSER)

现在滚动平滑且足够快,可以跟随鼠标移动:

笔记 我们expand=True在 ListView 构造函数中使用。为了正常工作,ListView 必须horizontal指定一个高度(或宽度,如果 )。您可以设置一个绝对大小,例如ListView(height=300, spacing=10),但在上面的示例中,我们让 ListView 占据页面上的所有可用空间,即展开。阅读更多关于Control.expand财产的信息。

GridView允许将控件排列到可滚动的网格中。

Column(wrap=True)您可以使用或制作“网格” Row(wrap=True),例如:

import os
import flet
from flet import Container, Page, Row, Text, alignment, border, border_radius, colors

os.environ["FLET_WS_MAX_MESSAGE_SIZE"] = "8000000"

def main(page: Page):
    r = Row(wrap=True, scroll="always", expand=True)
    page.add(r)

    for i in range(5000):
        r.controls.append(
            Container(
                Text(f"Item {i}"),
                width=100,
                height=100,
                alignment=alignment.center,
                bgcolor=colors.AMBER_100,
                border=border.all(1, colors.AMBER_400),
                border_radius=border_radius.all(5),
            )
        )
    page.update()

flet.app(target=main, view=flet.WEB_BROWSER)

尝试滚动和调整浏览器窗口的大小 - 一切正常,但非常滞后。

注意 在程序开始时,我们将FLET_WS_MAX_MESSAGE_SIZE环境变量的值设置为8000000- 这是 Flet Server 渲染页面可以接收的 WebSocket 消息的最大大小(以字节为单位)。默认大小为 1 MB,但描述 5,000 个容器控件的 JSON 消息的大小将超过 1 MB,因此我们将允许的大小增加到 8 MB。

通过 WebSocket 通道挤压大消息通常不是一个好主意,因此使用批量更新方法来控制通道负载。

GridView,类似于ListView,对于渲染很多children非常有效。让我们使用 GridView 来实现上面的示例:

import os
import flet
from flet import Container, GridView, Page, Text, alignment, border, border_radius, colors

os.environ["FLET_WS_MAX_MESSAGE_SIZE"] = "8000000"

def main(page: Page):
    gv = GridView(expand=True, max_extent=100, child_aspect_ratio=0.5)
    page.add(gv)

    for i in range(5000):
        gv.controls.append(
            Container(
                Text(f"Item {i}"),
                alignment=alignment.center,
                bgcolor=colors.AMBER_100,
                border=border.all(1, colors.AMBER_400),
                border_radius=border_radius.all(5),
            )
        )
    page.update()

flet.app(target=main, view=flet.WEB_BROWSER)

使用 GridView 滚动和调整窗口大小变得流畅且响应迅速!

您可以使用属性指定固定数量的行或列(运行)runs_count或使用属性的“平铺”的最大大小max_extent,因此运行次数可以自动变化。在我们的示例中,我们将最大平铺大小设置为 150 像素,并将其形状设置为“正方形”,其中child_aspect_ratio=1. child_aspect_ratio是每个孩子的横轴与主轴范围的比率。尝试将其更改为0.52

批量

page.update()被调用时,一条消息正在通过 WebSockets 发送到 Flet 服务器,其中包含自上次以来的页面更新page.update()。发送带有数千个添加控件的大型消息可能会使用户等待几秒钟,直到消息完全接收并呈现控件。

为了提高程序的可用性并将结果尽快呈现给用户,您可以批量发送页面更新。例如,以下程序将 5,100 个子控件分批添加到 ListView 中,每批 500 个项:

import flet
from flet import ListView, Page, Text

def main(page: Page):

    # add ListView to a page first
    lv = ListView(expand=1, spacing=10, item_extent=50)
    page.add(lv)

    for i in range(5100):
        lv.controls.append(Text(f"Line {i}"))
        # send page to a page
        if i % 500 == 0:
            page.update()
    # send the rest to a page
    page.update()

flet.app(target=main, view=flet.WEB_BROWSER)