TreeView 树形控件,支持展开/折叠、勾选框、图标装饰、Adapter 虚拟化数据源。
TreeView 以父子层级展示数据:
• 节点模型:每个节点有 Id、ParentId、Text、展开/勾选状态
• 虚拟化:仅渲染可见节点(展开状态下的扁平列表)
• 装饰:展开箭头、图标、勾选框
• Adapter:按需回调获取子节点数量与数据,适合超大树
| 函数 | 说明 |
|---|---|
int xuiTreeViewCreate(xui_context pCtx, xui_widget* ppW, const xui_tree_view_desc_t* pDesc) | 创建树 |
int xuiTreeViewAddNode(xui_widget pW, int iId, int iParentId, const char* sText) | 添加节点 |
int xuiTreeViewSetNodes(xui_widget pW, const xui_tree_view_node_t* pNodes, int iCount) | 批量设置 |
int xuiTreeViewSetNodeExpanded(xui_widget pW, int iNodeId, int bExpanded) | 展开/折叠 |
int xuiTreeViewToggleNode(xui_widget pW, int iNodeId) | 切换展开 |
int xuiTreeViewSetNodeChecked(xui_widget pW, int iNodeId, int bChecked) | 勾选 |
int xuiTreeViewSetSelected(xui_widget pW, int iNodeId) | 选中节点 |
int xuiTreeViewEnsureVisible(xui_widget pW, int iNodeId) | 滚动到可见 |
int xuiTreeViewSetAdapter(xui_widget pW, onCount, onNode, void* pUser) | 虚拟化适配器 |
int xuiTreeViewSetMetrics(xui_widget pW, float fH, float fIndent, float fPad, float fBorder) | 度量 |
gcc -O2 -I. -o ch147.exe ch147_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch147.exe
xui_tree_view_desc_t desc = { 0 };
xui_widget pTree;
xuiTreeViewCreate(pCtx, &pTree, &desc);
xuiWidgetSetRect(pTree, (xui_rect_t){0, 0, 260.0f, 500.0f});
// 构建树结构(Id, ParentId, Text)
xuiTreeViewAddNode(pTree, 1, 0, "src");
xuiTreeViewAddNode(pTree, 2, 1, "main.c");
xuiTreeViewAddNode(pTree, 3, 1, "render.c");
xuiTreeViewAddNode(pTree, 4, 0, "include");
xuiTreeViewAddNode(pTree, 5, 4, "xge.h");
// 默认展开根节点
xuiTreeViewSetNodeExpanded(pTree, 1, 1);
xuiTreeViewSetNodeExpanded(pTree, 4, 1);
xuiTreeViewSetSelect(pTree, OnTreeSelect, NULL);
xuiWidgetAddChild(pParent, pTree);将以下代码保存为 ch147_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 = "ch147 - TreeView";
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, 40, 40, 40, 40);
xuiSetRootWidget(g_pCtx, pRoot);
/* 创建树视图 */
xui_tree_view_desc_t tvd = { 0 };
xui_widget pTree;
xuiTreeViewCreate(g_pCtx, &pTree, &tvd);
xuiWidgetSetRect(pTree, (xui_rect_t){0, 0, 300, 500});
xuiWidgetAddChild(pRoot, pTree);
/* 构建树结构 (Id, ParentId, Text) */
xuiTreeViewAddNode(pTree, 1, 0, "src");
xuiTreeViewAddNode(pTree, 2, 1, "main.c");
xuiTreeViewAddNode(pTree, 3, 1, "render.c");
xuiTreeViewAddNode(pTree, 4, 1, "ui.c");
xuiTreeViewAddNode(pTree, 5, 0, "include");
xuiTreeViewAddNode(pTree, 6, 5, "xge.h");
xuiTreeViewAddNode(pTree, 7, 5, "xui.h");
xuiTreeViewAddNode(pTree, 8, 0, "build");
/* 默认展开根节点 */
xuiTreeViewSetNodeExpanded(pTree, 1, 1);
xuiTreeViewSetNodeExpanded(pTree, 5, 1);
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}