数据表(DataTable)是一种Material Design风格的数据表格。
一、基本用法
举例演示:创建了一个包含三列的DataTable(数据表),并设置了中文的列标题。添加了排序模拟,用print语句输出,没有真正实现排序逻辑。
import flet as ft
def main(page: ft.Page):
def sort_1(column_index, ascending):
print(f"正在对第 {column_index + 1} 列进行模拟排序,{'升序' if ascending else '降序'}")
# 创建数据表,设置列标题为中文
data_table = ft.DataTable(
columns=[
ft.DataColumn(ft.Text("姓名"), on_sort=lambda e: sort_1(e.column_index, e.ascending)),
ft.DataColumn(ft.Text("年龄"), numeric=True),
ft.DataColumn(ft.Text("城市")),
],
rows=[
ft.DataRow(
cells=[
ft.DataCell(ft.Text("lihua李华")),
ft.DataCell(ft.Text("25")),
ft.DataCell(ft.Text("北京")),
]
),
ft.DataRow(
cells=[
ft.DataCell(ft.Text("zhangwei张伟")),
ft.DataCell(ft.Text("30")),
ft.DataCell(ft.Text("上海")),
]
),
],
sort_column_index=0,
sort_ascending=True,
show_bottom_border=True,
)
page.add(data_table)
ft.app(target=main)
关键点:
- ft.DataTable 创建了一个数据表控件,它具有 columns 和 rows 属性,分别定义了表格的列和行。
- 每个 ft.DataColumn 对应于一列,可以指定列名、是否为数字列(numeric),以及点击列头时触发的排序事件处理函数(on_sort)。
- show_bottom_border=True 使得表格底部有一条边框线,提高视觉效果。
二、高级用法
(一)带排序功能
示例代码及解读如下:
import flet as ft
def main(page: ft.Page):
# 初始数据
data = [
{"name": "李华", "age": "25", "city": "北京"},
{"name": "张伟", "age": "30", "city": "上海"},
{"name": "王芳", "age": "22", "city": "广州"},
]
def sort_changed(e):
# 定义排序状态的非局部变量
nonlocal sort_column_index, sort_ascending
# 检查是否点击了相同的列
if e.column_index == sort_column_index:
# 如果是同一列,则切换排序方向
sort_ascending = not sort_ascending
else:
# 如果是不同的列,则设置为默认升序
sort_column_index = e.column_index
sort_ascending = True
# 打印当前排序状态
print(f"正在对第 {e.column_index + 1} 列进行排序,{'升序' if sort_ascending else '降序'}")
# 根据当前排序状态对数据进行排序
if sort_column_index == 0: # 姓名列
data.sort(key=lambda x: x["name"], reverse=not sort_ascending)
elif sort_column_index == 1: # 年龄列
data.sort(key=lambda x: int(x["age"]), reverse=not sort_ascending)
elif sort_column_index == 2: # 城市列
data.sort(key=lambda x: x["city"], reverse=not sort_ascending)
# 更新表格行
update_table()
def update_table():
# 更新行属性
table.rows = [
ft.DataRow(
cells=[
ft.DataCell(ft.Text(row["name"])),
ft.DataCell(ft.Text(row["age"])),
ft.DataCell(ft.Text(row["city"])),
]
)
for row in data
]
# 重置排序信息
table.sort_column_index = sort_column_index
table.sort_ascending = sort_ascending
# 更新页面以反映更改
page.update()
# 初始化排序状态
sort_column_index = None
sort_ascending = True
# 创建包含中文列标题的数据表
table = ft.DataTable(
columns=[
ft.DataColumn(ft.Text("姓名"), on_sort=sort_changed),
ft.DataColumn(ft.Text("年龄"), numeric=True, on_sort=sort_changed),
ft.DataColumn(ft.Text("城市"), on_sort=sort_changed),
],
rows=[
ft.DataRow(
cells=[
ft.DataCell(ft.Text(row["name"])),
ft.DataCell(ft.Text(row["age"])),
ft.DataCell(ft.Text(row["city"])),
]
)
for row in data
],
show_bottom_border=True,
)
page.add(table)
ft.app(target=main)
关键点:
- 定义排序状态变量。sort_column_index = None 用于跟踪当前排序的列索引, sort_ascending = True 用于指示排序方向,默认为升序。
- 实现排序变化事件处理函数sort_changed():
- nonlocal 关键字用于声明 sort_column_index 和 sort_ascending 不是局部变量,而是外层作用域(这里是 main 函数)中的变量。
- e.column_index 提供了用户点击的列索引。
- 如果点击的是同一列,则切换排序方向;如果是不同列,则设置为默认升序。
- 根据当前的排序状态,通过 lambda 表达式作为 key 参数传递给 list.sort() 方法来对 data 列表进行排序。对于年龄列,需要将字符串转换为整数以正确排序。
- 最后调用 update_table 函数更新表格显示。
- 更新表格行update_table():
- update_table 函数负责更新表格的行内容,它遍历 data 列表,并为每一行创建 DataRow 对象,每个 DataRow 包含多个 DataCell 对象,分别对应于表格中的单元格。
- 设置 table.sort_column_index 和 table.sort_ascending 来反映当前的排序状态。
- 调用 page.update() 来刷新页面,确保更改后的表格立即显示出来。
(二)带样式的数据表格
示例代码如下:
import flet as ft
def example():
return ft.DataTable(
width=600,
bgcolor="yellow",
border=ft.border.all(2, "red"),
border_radius=10,
vertical_lines=ft.border.BorderSide(3, "blue"),
horizontal_lines=ft.border.BorderSide(1, "green"),
sort_column_index=0,
sort_ascending=True,
heading_row_color=ft.Colors.BLACK12,
heading_row_height=100,
data_row_color={"hovered": "0x30FF0000"},
show_checkbox_column=True,
divider_thickness=0,
column_spacing=200,
columns=[
ft.DataColumn(
ft.Text("第一列"),
on_sort=lambda e: print(f"{e.column_index}, {e.ascending}"),
),
ft.DataColumn(
ft.Text("第二列"),
tooltip="这是第二列",
numeric=True,
on_sort=lambda e: print(f"{e.column_index}, {e.ascending}"),
),
],
rows=[
ft.DataRow(
[ft.DataCell(ft.Text("A")), ft.DataCell(ft.Text("1"))],
selected=True,
on_select_changed=lambda e: print(f"选择的行已更改: {e.data}"),
),
ft.DataRow([ft.DataCell(ft.Text("B")), ft.DataCell(ft.Text("2"))]),
],
)
def main(page:ft.Page):
page.title = "Flet 布局控件:ft.DataTable(数据表)"
page.window_width = 600
page.window_height = 400
page.window_center()
page.add(example())
ft.app(target=main)
三、DataTable属性
bgcolor
表格的背景颜色。
border
表格周围的边框。该值是 Border 类的实例。Border 类有以下属性描述矩形的 4 条边:
- bottom
- left
- right
- top
border_radius
边框的圆角。边框半径是 BorderRadius 类的实例。
border_radius.BorderRadius 类具有描述四个角值的以下属性:
- top_left (左上)
- top_right (右上)
- bottom_left (左下)
- bottom_right (右下)
可以使用构造函数分别设置所有角的值,也可以使用辅助方法:
- border_radius.all(value) (所有角相同)
- border_radius.horizontal(left: float = 0, right: float = 0) (水平方向)
- border_radius.vertical(top: float = 0, bottom: float = 0) (垂直方向)
- border_radius.only(top_left, top_right, bottom_left, bottom_right) (指定角)
checkbox_horizontal_margin
复选框周围的水平边距,如果显示的话。
clip_behavior
根据此选项,内容将被裁剪(或不裁剪)。值的类型为 ClipBehavior ,如果 border_radius!=None ,则默认为 ClipBehavior.ANTI_ALIAS ;否则为 ClipBehavior.HARD_EDGE 。
ClipBehavior 枚举具有以下值:
- NONE(无裁剪)
- ANTI_ALIAS(反锯齿)
- ANTI_ALIAS_WITH_SAVE_LAYER(带保存图层的反锯齿)
- HARD_EDGE(硬边缘)
column_spacing
每列内容之间的水平间距。
columns
描述表格列的 DataColumn 控件列表。
data_row_color
数据行的背景颜色。
有效的背景颜色可以取决于ControlState状态, 即如果行被选中、按下、悬停、聚焦、禁用或启用。颜色作为覆盖层绘制到行上。为确保行的 InkWell 可见(当按下、悬停和聚焦时),建议使用半透明的背景颜色。
data_row_min_height
每行的最小高度(不包括包含列标题的行)。 默认值为“48.0”,且必须小于或等于“data_row_max_height”。
data_row_max_height
每行的最大高度(不包括包含列标题的行)。将其设置为 float("inf") 以使每行的高度根据其内容自动调整。
默认值为 48.0 ,并且必须大于或等于 data_row_min_height 。
data_text_style
数据行的文本样式。是 TextStyle 类的实例。
divider_thickness
出现在 TableRow 之间的分隔线的宽度。必须大于或等于零。该值默认为 1.0。
gradient
表格的背景渐变色。值类型为 Gradient
heading_row_alignment
标题行对齐方式。该值的类型为MainAxisAlignment。
heading_row_color
标题行的背景颜色。
有效的背景颜色可以根据 ControlState 状态(即行是否按下、悬停、聚焦时进行排序)进行调整。颜色作为行的覆盖层进行绘制。为了确保行的墨水效果可见(在按下、悬停和聚焦时),建议使用半透明的颜色。
heading_row_height
标题行的高度。
heading_text_style
标题行的文本样式。是 TextStyle 类的实例。
horizontal_lines
设置行之间水平线的颜色和宽度。是 BorderSide 类的实例。
horizontal_margin
表格边缘与每行第一个和最后一个单元格内容之间的水平边距。显示复选框时,它也是复选框与第一个数据列内容之间的边距。
rows
定义表格行的 DataRow 控件列表。
show_bottom_border
是否显示表格底部的边框。默认情况下,不显示底部边框以允许通过装饰定义表格周围的边框。
show_checkbox_column
是否应显示可选行的复选框。
如果为 True,则在每个可选行的开头放置一个 Checkbox。然而,如果任何行的 DataRow.on_select_changed 未设置,即使该值为 True,也不会放置复选框。
如果为 False,则所有行都不会显示 Checkbox。
sort_ascending
指定的 sort_column_index 列是否按升序排序。
如果为 True,则顺序为升序(意味着当前排序列的最小值的行在表格的最前面)。
如果为 False,则顺序为降序(意味着当前排序列的最小值的行在表格的最后面)。
sort_column_index
当前主要排序键的列。如果指定,则表示数据按所指示的列进行排序。该数字必须对应于 columns 中相关列的索引。设置此值会导致相关列显示排序指示器。当此值为 None 时,表示表格的排序顺序不对应于任何列。
vertical_lines
设置列之间垂直线的颜色和宽度。是 BorderSide 类的实例。
四、DataTable 事件
on_select_all
当用户使用标题行中的复选框选择或取消选择每行时调用。
如果为 None,则适当调用表格中每行的 DataRow.on_select_changed 回调。
要控制特定行是否可选,请参见 DataRow.on_select_changed。此回调仅在任何行可选时相关。
五、DataColumn —— DataTable 的列配置
每个要显示在表格中的列都必须提供一个列配置。
label
列标题。通常是一个 Text 控件。它也可以是一个 Icon(通常使用大小18),或一个带有图标和一些文本的 Row。
numeric
此列是否表示数字数据。包含数字数据的列的单元格内容是右对齐的。
tooltip
列标题的工具提示。这是列标题的更长描述,用于标题可能已缩写以保持列宽合理的情况。
六、DataColumn 事件
on_sort
当用户请求使用此列排序表格时调用。如果未设置,则不考虑该列可排序性。
七、DataRow —— DataTable 的行配置和单元格数据
每个要显示在表格中的行都必须提供一个行配置。该行的表格数据在 DataRow 对象的 cells 属性中提供。
cells
该行的数据 - DataCell 控件列表。
必须有与表格中的列数完全相同的单元格。
color
该行的颜色。默认情况下,颜色是透明的,除非被选中。选中的行有灰色半透明颜色。
有效颜色可以根据 ControlState 状态(如果行被选中、按下、悬停、聚焦、禁用或启用)进行调整。颜色作为行的覆盖层进行绘制。为了确保行的墨水效果可见(在按下、悬停和聚焦时),建议使用半透明颜色。
selected
行是否被选中。
如果 on_select_changed 对于表格中的任何行不是null,则在每行的开头显示一个复选框。如果行被选中 (True),则复选框将被选中,行将被高亮显示。
否则,复选框(如果存在)将不会被选中。
八、DataRow 事件
on_long_press
如果行被长按,则调用。
如果行中的 DataCell 定义了其 DataCell.on_tap、DataCell.on_double_tap、DataCell.on_long_press、DataCell.on_tap_cancel 或 DataCell.on_tap_down 回调,则该回调行为会覆盖该特定单元格的行手势行为。
on_select_changed
当用户选择或取消选择可选行时调用。
如果这不是null,则该行是可选的。行的当前选择状态由 selected 给出。
如果任何行是可选的,则表格的标题行将有一个复选框,该复选框可以选择所有可选行(并且如果所有行都被选中则会选中),每行将有一个复选框以切换该行。
如果行的 on_select_changed 回调为null,则在确定“全选”复选框的状态时会忽略该行,其复选框将被禁用。
如果行中的 DataCell 定义了其 DataCell.on_tap 回调,则该回调行为会覆盖该特定单元格的行手势行为。
九、DataCell —— DataTable 单元格的数据
每个 DataRow 必须提供一个 DataCell 对象列表。
content
行的数据。通常是一个 Text 控件或一个 Dropdown 控件。
如果单元格没有数据,则应提供一个带有占位符文本的 Text 控件,并将 placeholder 设置为 True。
此控件只能有一个子控件。要布置多个子控件,请将此控件的子控件设为具有 controls 属性的 Row、Column 或 Stack 等控件,然后为该控件提供子控件。
placeholder
子控件是否实际上是占位符。如果为 True,则单元格的默认文本样式会更改为适用于占位符文本。
show_edit_icon
是否在单元格末尾显示编辑图标。
这不会使单元格实际上可编辑;调用方必须实现所需的编辑行为(从 on_tap 回调启动)。
如果设置了此选项,还应设置 on_tap,否则点击图标将无效。
十、DataCell 事件
on_double_tap
当双击单元格时调用。如果指定,点击单元格将调用此回调,否则(点击单元格将尝试选择行(如果提供了 DataRow.on_select_changed )。
on_long_press
如果长按单元格,则调用。
如果指定,点击单元格将调用此回调,否则(点击单元格将尝试选择行(如果提供了 DataRow.on_select_changed )。
on_tap
如果点击单元格,则调用。
如果指定,点击单元格将调用此回调,否则(点击单元格将尝试选择行(如果提供了 DataRow.on_select_changed )。
on_tap_cancel
如果用户取消了在单元格上开始的点击,则调用。
如果指定,点击单元格将调用此回调,否则(点击单元格将尝试选择行(如果提供了 DataRow.on_select_changed )。
on_tap_down
如果点击单元格,则调用。
如果指定,点击单元格将调用此回调,否则(点击单元格将尝试选择行(如果提供了 DataRow.on_select_changed )。
(汇报完毕,感谢收看!)