TableView 多列表格控件,支持列定义、排序、单元格选中、列宽拖拽、自定义渲染器与合并单元格。
TableView 是只读多列表格(编辑功能由 TableGrid 提供):
• Column:列定义(标题、宽度、对齐、可排序)
• Row:行数据(字符串数组或 Adapter 回调)
• 排序:点击表头触发排序回调
• 虚拟化:仅渲染可见行,支持万行数据
• 合并:MergeProvider 回调实现跨行/跨列合并
| 函数 | 说明 |
|---|---|
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;
}