MujicaUI

Data · #071

DataTable 浅色主题渲染快照
浅色 · 渲染快照
DataTable 深色主题渲染快照
深色 · 渲染快照

071 DataTable · 数据表格

用途

按列展示数据行,只构建可见行。提供排序、筛选、多选、列宽、列顺序、列显隐与自定义单元格。行与列都以稳定 ID 保存状态:排序、筛选或调整列之后,选择仍指向同一条数据。默认使用本地排序与筛选(仅在数据、排序或筛选条件变化时计算一次并缓存);Controlled 模式下按调用方顺序显示,调用方在 SortChanged() 时自行查询。

最小示例

type relic struct {
	ID   int
	Name string
	Age  int
}
rows := []relic{{1, "Censer", 300}, {2, "Altar", 120}, {3, "Bell", 80}}
var state data.DataTableState[int]
opts := data.DataTableOptions[relic, int]{
	Key: func(r relic) int { return r.ID },
	Columns: []data.DataColumn[relic]{
		{ID: "name", Title: "Name", Sortable: true,
			Text:    func(r relic) string { return r.Name },
			Compare: func(a, b relic) int { return cmp.Compare(a.Name, b.Name) }},
		{ID: "age", Title: "Age", Width: 80, Align: ui.End, Sortable: true,
			Text:    func(r relic) string { return strconv.Itoa(r.Age) },
			Compare: func(a, b relic) int { return cmp.Compare(a.Age, b.Age) }},
	},
}
view := func(c *ui.Context) {
	core.Use(c, core.Settings{})
	data.DataTable(c, &state, rows, opts).Element.Size(360, 240)
}
ui.Render(view, 400, 300, 1)

参数

func DataTable[R any, K comparable](c *ui.Context, s *DataTableState[K], rows []R, opts DataTableOptions[R, K]) DataTableView。表格上方有“列”按钮,弹层中每列提供显隐勾选框、升序/降序排序、左移/右移与减小/增大列宽(每次 16 DIP),这是排序、列顺序与列宽的键盘入口。另有纯函数 DataTableRows(rows, cols, sort, filter) []int(本地排序筛选辅助,返回行下标)。

DataTableState 字段:Sort ui.SortOrder、Filter string(不区分大小写包含匹配全部列的 Text)、Hidden map[string]bool(按列 ID 隐藏)、Layout ui.TableLayout(用户拖动得到的列顺序与列宽,可保存恢复)、Selection ui.Selection[K](多选)。方法:Selected()、Rows()(筛选后行数)。

字段类型默认值含义
Columns[]DataColumn[R]必填列定义:ID(必填、唯一)、Title、Width(0 表示分配剩余宽度)、MinWidth、Align、Sortable、Compare(本地排序比较函数)、Text(必填,纯文本,用于筛选与默认单元格)、Cell(自定义单元格)。
Keyfunc(R) K必填行的稳定 ID;重复时 panic。
Multipleboolfalse多选:首列显示勾选框,点击勾选框增减,Cmd/Ctrl、Shift 点击与 Cmd/Ctrl+A。
Controlledboolfalse受控模式:不在本地排序筛选。
Versionint0原地修改 rows 后递增,通知缓存失效;换新切片无需递增。
StatusDataStatusDataReady加载状态:DataLoading 首次加载(无行时显示加载标记)、DataLoadingMore 追加加载(行下方显示“正在加载更多”)、DataFailed 失败(显示错误与“重试”)。
Errorstring内置“加载失败”DataFailed 时显示的具体错误。
Emptystring内置“暂无数据”无数据时的说明文字。

状态

默认、表头悬停、排序箭头(升/降)、行悬停、选中行(Selection 背景 + Text 文字;单选首列 AccentText 菱形,多选首列勾选框)、聚焦(表格外焦点环)、加载、追加加载、失败、空、无匹配。数据行与表头高度不低于当前密度的数据行高(28/36/44 DIP),并随文本缩放增高;多选勾选框保留完整的 28 × 28 DIP 命中区域。

事件

Changed():选择变化(含勾选框);Submitted():Enter 或双击;SortChanged():点击表头或列菜单改变了 State.Sort;Retried():点击“重试”。

键盘操作

  • ↑/↓、Home/End:移动选择;Enter:提交;输入字母按首个可见列定位。
  • 多选:Shift/Cmd(Ctrl) 配合点击或方向键;Cmd/Ctrl+A 全选。
  • 表头:点击排序、再次点击反向;拖动表头边缘调整列宽,双击适配内容;拖动表头移动列。
  • 列菜单:Tab 到“列”按钮,Enter 打开;Tab 在各列的勾选框与排序、移动、列宽按钮间移动,Enter/Space 执行;Escape 关闭。
  • 多选勾选框可用 Tab 到达,Space 切换。

限制

  • MyGo ui.Table 只按调用方给出的顺序显示(docs/ui/table.md “Sorting”),因此本组件在本地完成排序,或在受控模式下交给调用方。
  • 表头内容只能是 Title 文字且只响应指针(ui/table.go tableHeader),因此全选使用 Cmd/Ctrl+A,键盘排序与调整列通过列菜单。
  • 共享列宽的列在列菜单中从 max(MinWidth, 120) DIP 开始调整。
  • 单选的跟随由组件按键重新定位,跨越任意距离都有效;多选的键盘锚点在大规模重排后由 MyGo 重置(ui/list.go:30)。
  • 删除的数据行对应的选择会在数据变化时清除;被筛选隐藏的行保留选择。
  • 10 万行 × 10 列:测试统计“最后一帧构建过单元格的行数”不超过 16,并断言重复帧不再调用比较函数(data_table_test.go)。