虚拟容器与大数据集控件¶
这组文档面向需要在 EmbeddedGUI 中承载大数据集、可变尺寸内容和复杂交互状态的场景。
它讲的不是传统 List,而是建立在 virtual_viewport 之上的一整套虚拟容器家族:
virtual_viewportvirtual_listvirtual_pagevirtual_stripvirtual_gridvirtual_section_listvirtual_treevirtual_stage
如果你的界面只有十几个固定子控件,或者传统 List 已经足够,就不需要引入这套体系。
如果你的场景满足下面任意一条,建议优先阅读本章:
数据量可能达到几百到上千条
item 需要按可见区动态创建
item 尺寸会变化
数据会频繁插入、删除、移动、patch
需要围绕
stable_id做精确定位和局部刷新item 有动画态、编辑态、展开态、选中态,需要避免因回收而丢状态
阅读顺序¶
你会在这组文档里看到什么¶
为什么这套控件不是单纯的 ListView
stable_id、slot 复用、keepalive、state cache的设计目的各个 virtual 容器的适用边界
带截图的语义差异对比
面向
virtual_viewport、virtual_page、virtual_strip、virtual_grid、virtual_section_list、virtual_tree的完整选型与接入说明汇总各示例入口、头文件、helper 和通知接口
解释状态缓存、
keepalive、对象池复用与验证流程
params、data_source、setup应该怎么写各容器最小接入骨架
常用 helper 和通知接口怎么选
动画、点击、滚动、定位和验证流程
快速选型表¶
容器 |
最小业务单元 |
典型场景 |
|---|---|---|
|
完全自定义 |
画布块、聊天气泡、看板卡、自定义混排 |
|
row |
feed、日志、普通消息列表 |
|
section / module |
仪表盘、设置页大区块、详情页模块 |
|
rail item |
海报带、时间轴条带、播放队列 |
|
tile / card |
商品宫格、缩略图墙、tile 面板 |
|
section header + item |
设置分组、工单分组、消息分组 |
|
node |
文件树、拓扑树、组织树、任务树 |
|
fixed node / absolute block |
固定画布、绝对定位节点页、仪表盘总览、设备看板 |
与传统 List 和高层 ListView / GridView 的关系¶
传统 列表控件 解决的是“小规模、固定结构的滚动条目”。
ListView / GridView 解决的是“数据量很大,但业务层只想维护 data_model + holder_ops,并直接在 holder 里放真实控件”。
virtual 家族解决的是“更底层、更通用的大数据集、按需创建、状态恢复、精确通知”问题。
因此在文档和工程实践里,可以这样区分:
条目数量很小,且没有复杂局部状态:优先传统
List条目数量很大,但只是常见纵向 row 或二维 tile,且想直接写
ViewHolder + DataModel:优先 列表与网格控件 里的ListView / GridView需要
section / tree / page / stage语义,或者要直接控制 raw adapter / slot / state cache 细节:优先 virtual 家族
相关示例¶
example/HelloVirtual/virtual_viewport_basic/example/HelloVirtual/virtual_viewport/example/HelloVirtual/virtual_page_basic/example/HelloVirtual/virtual_page/example/HelloVirtual/virtual_strip_basic/example/HelloVirtual/virtual_strip/example/HelloVirtual/virtual_grid_basic/example/HelloVirtual/virtual_grid/example/HelloVirtual/virtual_section_list_basic/example/HelloVirtual/virtual_section_list/example/HelloVirtual/virtual_tree_basic/example/HelloVirtual/virtual_tree/example/HelloVirtual/virtual_stage_basic/example/HelloVirtual/virtual_stage_showcase/example/HelloVirtual/virtual_stage/
virtual_stage 入口说明¶
如果你想先理解 raw virtual_viewport 的最小接法,建议先看 example/HelloVirtual/virtual_viewport_basic/,它去掉了顶部摘要 Header,只保留一个简单 action bar、一个纵向 viewport 和两种基础行类型,聚焦 init_with_setup、外置 item 状态、点击/拖动回查、单项刷新和 ensure_item_visible_by_stable_id()。
virtual_stage 不属于“滚动数据集容器”的那条线,它更适合固定页面里有很多绝对定位节点、但只有少量节点需要临时 materialize 成真实控件的场景。
推荐阅读顺序:
先看
example/HelloVirtual/virtual_stage_basic/,这是最小可用接法,聚焦EGUI_VIEW_VIRTUAL_STAGE_NODE_ARRAY_INTERACTIVE_BRIDGE_INIT_WITH_LIMIT(...)、EGUI_VIEW_VIRTUAL_STAGE_INIT_ARRAY_BRIDGE(...)、EGUI_VIEW_VIRTUAL_STAGE_ADD_ROOT(...)、EGUI_VIEW_VIRTUAL_STAGE_RESOLVE_ID_BY_VIEW(...)、EGUI_VIEW_VIRTUAL_STAGE_TOGGLE_PIN(...)、外置状态、pin/reset。再看
example/HelloVirtual/virtual_stage_showcase/,这是 showcase 风格的对比 case,面板和说明走 render-only,8 个代表性控件保持真实 widget,适合和HelloShowcase对照看。最后看
example/HelloVirtual/virtual_stage/,这是复杂 cockpit 场景,覆盖更多节点类型、keepalive 和状态恢复。设计与 API 细节见
doc/source/architecture/virtual_stage.md。
补充两条容易踩坑的语义:
EGUI_VIEW_VIRTUAL_STAGE_PIN(...)不是“先记个愿望,之后再补节点”,它只接受当前已经存在且可 materialize 的节点;render-only、hidden 或不存在的节点都会返回失败。如果节点原来没有 live slot,但你把它切成
KEEPALIVE、或者把一个已 pin 节点从 hidden/零尺寸恢复为可见,记得继续发notify_node_changed()/notify_node_bounds_changed(),让virtual_stage重新把它拉回 slot。
相关头文件¶
src/widget/egui_view_virtual_viewport.hsrc/widget/egui_view_virtual_list.hsrc/widget/egui_view_virtual_page.hsrc/widget/egui_view_virtual_strip.hsrc/widget/egui_view_virtual_grid.hsrc/widget/egui_view_virtual_section_list.hsrc/widget/egui_view_virtual_tree.hsrc/widget/egui_view_virtual_stage.h
virtual_page 入门示例¶
如果用户刚开始接 virtual_page,建议先看 example/HelloVirtual/virtual_page_basic/。
这个例程刻意把内容收缩到最小闭环:
一个简单的 action bar
一个纵向
virtual_page三种 section 语义:hero / metric / checklist
它重点覆盖:
init_with_setup外置 section 状态
点击回查 section
notify_section_changed_by_stable_id()notify_section_resized_by_stable_id()scroll_to_section_by_stable_id()/ensure_section_visible_by_stable_id()
读完 virtual_page_basic 后,再看 example/HelloVirtual/virtual_page/,更容易理解复杂场景里的 keepalive、state cache 和更丰富的模块布局。
virtual_strip 入门示例¶
如果用户刚开始接 virtual_strip,建议先看 example/HelloVirtual/virtual_strip_basic/。
这个例程刻意把内容收缩到最小闭环:
一个简单的 action bar
一个横向
virtual_strip一种基础卡片视图,带三种宽度变化
它重点覆盖:
init_with_setup外置 item 状态
resolve_item_by_view()点击回查notify_item_changed_by_stable_id()/notify_item_resized_by_stable_id()scroll_to_stable_id()/ensure_item_visible_by_stable_id()
读完 virtual_strip_basic 后,再看 example/HelloVirtual/virtual_strip/,更容易理解复杂场景里的 scene 切换、keepalive、state cache 和 richer 轨道语义。
virtual_grid 入门示例¶
如果用户刚开始接 virtual_grid,建议先看 example/HelloVirtual/virtual_grid_basic/。
这个例程刻意把内容收缩到最小闭环:
一个简单的 action bar
一个纵向
virtual_grid一种基础 tile 视图,配几种高度变化
它重点覆盖:
init_with_setup外置 item 状态
resolve_item_by_view()点击回查notify_item_changed_by_stable_id()/notify_item_resized_by_stable_id()set_column_count()/ensure_item_visible_by_stable_id()
读完 virtual_grid_basic 后,再看 example/HelloVirtual/virtual_grid/,更容易理解复杂场景里的 row slot、列切换、自适应高度和 richer grid 语义。
virtual_section_list 入门示例¶
如果用户刚开始接 virtual_section_list,建议先看 example/HelloVirtual/virtual_section_list_basic/。
这个例程刻意把内容收缩到最小闭环:
一个简单的 action bar
一个纵向
virtual_section_list明确区分的
section header + grouped row
它重点覆盖:
init_with_setup外置 section / item 状态
resolve_entry_by_view()回查 header 或 itemheader 折叠 / 展开后的
notify_data_changed()item patch 后的
notify_item_changed_by_stable_id()/notify_item_resized_by_stable_id()scroll_to_item_by_stable_id()/ensure_entry_visible_by_stable_id()
读完 virtual_section_list_basic 后,再看 example/HelloVirtual/virtual_section_list/,更容易理解复杂场景里的 insert / remove、state cache、keepalive 和 pulse 动画。
virtual_tree 入门示例¶
如果用户刚开始接 virtual_tree,建议先看 example/HelloVirtual/virtual_tree_basic/。
这个例程刻意把内容收缩到最小闭环:
一个简单的 action bar
一个纵向
virtual_tree三层最小树结构:root / group / task
它重点覆盖:
init_with_setup外置树节点状态
点击回查 node
branch 折叠 / 展开后的
notify_data_changed()task patch 后的
notify_node_changed_by_stable_id()/notify_node_resized_by_stable_id()scroll_to_node_by_stable_id()/ensure_node_visible_by_stable_id()
读完 virtual_tree_basic 后,再看 example/HelloVirtual/virtual_tree/,更容易理解复杂场景里的 keepalive、state cache、pulse 动画和更大的可见节点流。