Chapter 148 · XUI 容器与导航

TableView 表格

TableView 多列表格控件,支持列定义、排序、单元格选中、列宽拖拽、自定义渲染器与合并单元格。

148

概念

TableView 是只读多列表格(编辑功能由 TableGrid 提供):
• Column:列定义(标题、宽度、对齐、可排序)
• Row:行数据(字符串数组或 Adapter 回调)
• 排序:点击表头触发排序回调
• 虚拟化:仅渲染可见行,支持万行数据
• 合并:MergeProvider 回调实现跨行/跨列合并

API 速查

函数说明
int xuiTableViewCreate(xui_context pCtx, xui_widget* ppW, const xui_table_view_desc_t* pDesc)创建表格
int xuiTableViewSetColumns(xui_widget pW, const xui_table_view_column_t* arr, int iCount)定义列
int xuiTableViewSetRows(xui_widget pW, const xui_table_view_row_t* arr, int iCount)设置行数据
int xuiTableViewSetAdapter(xui_widget pW, onCount, onCell, void* pUser)虚拟化适配器
int xuiTableViewSetSort(xui_widget pW, xui_table_view_sort_proc onSort, void* pUser)排序回调
int xuiTableViewSetSelectedRow(xui_widget pW, int iRow)选中行
int xuiTableViewSetSelectedCell(xui_widget pW, int iRow, int iCol)选中单元格
int xuiTableViewSetColumnWidth(xui_widget pW, int iCol, float fWidth)列宽
int xuiTableViewSetCellRenderer(xui_widget pW, onRender, void* pUser)自定义单元格渲染
int xuiTableViewEnsureCellVisible(xui_widget pW, int iRow, int iCol)滚动到单元格

编译本章示例

gcc -O2 -I. -o ch148.exe ch148_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch148.exe

示例:进程列表

xui_table_view_desc_t desc = { 0 };

xui_widget pTable;
xuiTableViewCreate(pCtx, &pTable, &desc);
xuiWidgetSetRect(pTable, (xui_rect_t){0, 0, 600.0f, 400.0f});

// 定义列
xui_table_view_column_t cols[3] = {
    { "名称",   200.0f, 0, 1 },
    { "PID",    80.0f,  1, 1 },
    { "内存",   120.0f, 1, 1 },
};
xuiTableViewSetColumns(pTable, cols, 3);

// 设置行数据
xuiTableViewSetRows(pTable, rows, iRowCount);
xuiTableViewSetSort(pTable, OnSort, NULL);
xuiTableViewSetSelect(pTable, OnSelect, NULL);

xuiWidgetAddChild(pParent, pTable);

完整代码

将以下代码保存为 ch148_main.c,编译后运行即可看到表格视图效果:

#include "xge.h"
#include "xui.h"
#include <stdio.h>

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    float mx, my;
    xgeMouseGet(&mx, &my);
    xuiInputPointerMove(g_pCtx, mx, my);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, 0);
    else
        xuiInputPointerUp(g_pCtx, 0);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = { 0 };
    d.iWidth = 800; d.iHeight = 600;
    d.sTitle = "ch148 - TableView";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);

    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    /* 根容器 */
    xui_widget pRoot;
    xuiWidgetCreate(g_pCtx, &pRoot);
xuiWidgetSetLayoutType(pRoot, XUI_LAYOUT_COLUMN);
    xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 600});
    xuiWidgetSetPadding(pRoot, 20, 20, 20, 20);
    xuiSetRootWidget(g_pCtx, pRoot);

    /* 创建表格 */
    xui_table_view_desc_t tvd = { 0 };
    xui_widget pTable;
    xuiTableViewCreate(g_pCtx, &pTable, &tvd);
    xuiWidgetSetRect(pTable, (xui_rect_t){0, 0, 760, 560});
    xuiWidgetAddChild(pRoot, pTable);

    /* 定义列 */
    xui_table_view_column_t cols[3] = {
        { "名称", 300.0f, 0, 1 },
        { "PID",  100.0f, 1, 1 },
        { "内存", 150.0f, 1, 1 },
    };
    xuiTableViewSetColumns(pTable, cols, 3);

    /* 设置行数据 */
    static xui_table_view_row_t rows[5];
    static const char* data[][3] = {
        { "explorer.exe", "1024", "85 MB" },
        { "chrome.exe",   "2048", "320 MB" },
        { "code.exe",     "3072", "210 MB" },
        { "gcc.exe",      "4096", "45 MB" },
        { "game.exe",     "5120", "512 MB" },
    };
    for (int i = 0; i < 5; i++) {
        rows[i].ppCells = data[i];
        rows[i].iCellCount = 3;
    }
    xuiTableViewSetRows(pTable, rows, 5);

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • SetColumns:定义列标题、宽度、对齐、是否可排序。
  • SetRows:传入行数据数组,每行包含单元格文本指针。
  • 虚拟化:小数据用 SetRows,大数据用 Adapter 按需加载。
  • 内建滚动:行多时自动显示滚动条,仅渲染可见行。

要点与陷阱

  • Adapter vs SetRows:小数据用 SetRows,大数据用 Adapter 虚拟化。
  • 排序:点击表头触发回调,应用层负责实际数据排序后 Refresh。
  • ColumnResize:用户拖拽列边界触发回调,可持久化列宽。
  • CellRenderer:自定义绘制进度条、图标、颜色标记等。
  • MergeProvider:返回合并区域实现报表样式。

进阶练习

  1. 可排序表格:点击表头切换升序/降序,箭头指示方向。
  2. 斑马纹 + 悬停高亮:通过 ColorStyle 配置交替行颜色。
TableView 表格效果
图:TableView 表格渲染效果