You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ImGui::ListBox中使用存储自定义对象的vector?

问题原因

你遇到编译错误的核心原因是Dear ImGui 原生未提供直接接收std::vector<自定义类型>作为入参的ImGui::ListBox重载版本。原生ListBox仅支持两类传入方式:一类是直接传入C风格字符串数组,另一类是传入自定义渲染回调、数据指针来适配任意自定义类型的展示需求。

实现方法

方法1:使用回调适配版ListBox(实现简单,适合纯文本展示项)

这个方案用ImGui预留的自定义Getter回调,把vector中的自定义对象格式化成展示文本,不需要额外写渲染逻辑,代码量最小。

  • 首先匹配ImGui要求的回调签名,回调内部根据索引从vector中取出对应Waypoint对象,把所有属性格式化成字符串即可。
  • 调用ListBox时把vector指针作为用户数据传入,同时传入vector当前长度作为总项数,天然支持每帧动态更新内容。

完整示例代码:

// 自定义Waypoint类沿用你的定义
class Waypoint {
public:
    int x, y, z;
    char action;
};

// 每帧渲染逻辑中
std::vector<Waypoint> listbox_items;
// 测试填充数据
Waypoint wp1;
wp1.action = 'R';
wp1.x = 100;
wp1.y = 100;
wp1.z = 7;
listbox_items.push_back(wp1);
Waypoint wp2;
wp2.action = 'S';
wp2.x = 100;
wp2.y = 100;
wp2.z = 6;
listbox_items.push_back(wp2);

static int listbox_item_current = 0; // 选中索引从0开始,初始值1代表默认选中第二项
ImGui::ListBox(
    "listbox::Cavebot",
    &listbox_item_current,
    // 无捕获lambda可直接转为ImGui要求的函数指针,无需单独定义全局函数
    [](void* user_data, int idx, const char** out_text) -> bool {
        const auto* waypoint_vec = static_cast<const std::vector<Waypoint>*>(user_data);
        // 索引越界直接返回false
        if (idx < 0 || idx >= waypoint_vec->size())
            return false;
        const Waypoint& wp = (*waypoint_vec)[idx];
        // 静态缓冲区存储格式化后的展示文本,确保指针在回调返回后仍有效
        static char display_buf[128];
        snprintf(display_buf, sizeof(display_buf), 
            "Waypoint %d | Action: %c | Position: (%d, %d, %d)",
            idx, wp.action, wp.x, wp.y, wp.z);
        *out_text = display_buf;
        return true;
    },
    (void*)&listbox_items, // 把vector指针作为用户数据传入回调
    listbox_items.size() // 传入当前vector的总长度
);

// 后续可直接通过listbox_item_current获取选中的航点对象
if (listbox_item_current >= 0 && listbox_item_current < listbox_items.size())
{
    Waypoint& selected = listbox_items[listbox_item_current];
    // 编写选中后的业务逻辑即可
}

方法2:手动控制列表项渲染(灵活度高,支持自定义样式)

如果你需要给列表项加彩色文本、图标、按钮等复杂元素,直接用BeginListBox/EndListBox接口自行循环渲染每一项,可控性更强:

if (ImGui::BeginListBox("listbox::Cavebot"))
{
    for (int i = 0; i < listbox_items.size(); i++)
    {
        const bool is_selected = (listbox_item_current == i);
        const Waypoint& wp = listbox_items[i];
        
        // 自定义渲染逻辑:比如动作类型用橙色高亮
        ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "[%c]", wp.action);
        ImGui::SameLine();
        ImGui::Text("Pos: (%d, %d, %d)", wp.x, wp.y, wp.z);

        // 处理点击选中
        if (ImGui::IsItemClicked())
            listbox_item_current = i;
        
        // 给选中项加默认高亮
        if (is_selected)
            ImGui::SetItemDefaultFocus();
    }
    ImGui::EndListBox();
}
注意事项
  • 两种方案都天然支持动态更新:每帧渲染时会自动读取vector的最新长度和内容,增删元素、修改属性后下一帧会自动展示最新结果,不需要额外调用刷新接口。
  • 动态增删vector元素后,注意检查listbox_item_current是否越界,如果越界要手动重置为合法值(比如设为0,或者最后一项的索引),避免出现选中空项的问题。
  • 回调中不要使用栈上临时字符数组存储展示文本,否则会出现内存访问错误,必须用静态缓冲区或者全局缓冲区保证指针有效性。

内容的提问来源于stack exchange,提问作者kuhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:01:07