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

基于C++、OpenGL与ImGui的游戏引擎:可停靠子窗口实现问题

实现ImGui可停靠子窗口的解决方案

1. 确认Docking功能已启用

在ImGui初始化阶段,必须开启Docking配置(如果还没做的话):

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // 核心:启用Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // 可选:支持跨窗口停靠/独立窗口拖出

2. 改造主窗口为Dock根容器

你的全屏主窗口需要先创建一个覆盖整个窗口区域的DockSpace,作为子窗口的停靠载体。修改主窗口代码:

ImGuiWindowFlags main_win_flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse;
// 强制主窗口占满整个视口
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->Pos);
ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size);
ImGui::Begin("ImGUI Main Window", NULL, main_win_flags);

// 创建DockSpace,参数0,0表示自动填充主窗口剩余区域
ImGuiID dockspace_id = ImGui::GetID("EngineDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode);

ImGui::End();

ImGuiDockNodeFlags_PassthruCentralNode可选,作用是让中央停靠区域透传鼠标事件(比如你的游戏视图需要接收输入时有用)。

3. 创建可停靠的子窗口

直接创建普通窗口即可,它们会自动识别主窗口的DockSpace,支持拖拽停靠、移动、标签页合并:

// 示例:Inspector窗口
static bool show_inspector = true;
if (show_inspector) {
    ImGui::Begin("Inspector", &show_inspector);
    ImGui::Text("Inspector Panel Content");
    // 这里添加你的窗口控件逻辑
    ImGui::End();
}

// 示例:Scene视图窗口
static bool show_scene = true;
if (show_scene) {
    ImGui::Begin("Scene View", &show_scene);
    ImGui::Text("Scene Render Content");
    ImGui::End();
}

这些窗口默认就支持拖拽到主窗口的DockSpace中,停靠后会自动适配区域,也可以拖动边缘调整大小,或者拖出成为独立窗口。

4. 预设初始布局(可选)

如果需要首次启动就有固定的停靠布局,可在第一次运行时通过DockBuilder构建:

static bool dock_layout_initialized = false;
if (!dock_layout_initialized) {
    dock_layout_initialized = true;
    ImGui::DockBuilderRemoveNode(dockspace_id); // 清除默认布局
    ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace);
    ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size);

    // 分割布局:左侧Inspector(占25%宽度),右侧Scene(占75%)
    ImGuiID main_dock = dockspace_id;
    ImGuiID left_dock = ImGui::DockBuilderSplitNode(main_dock, ImGuiDir_Left, 0.25f, NULL, &main_dock);
    ImGuiID right_dock = ImGui::DockBuilderSplitNode(main_dock, ImGuiDir_Right, 0.75f, NULL, &main_dock);

    // 将窗口绑定到对应Dock节点
    ImGui::DockBuilderDockWindow("Inspector", left_dock);
    ImGui::DockBuilderDockWindow("Scene View", right_dock);

    ImGui::DockBuilderFinish(dockspace_id);
}

问题排查

  • 子窗口停靠后全屏:检查DockSpace的尺寸是否设为ImVec2(0.0f, 0.0f),确保它填充整个主窗口区域。
  • 子窗口无法移动:确认子窗口没有设置ImGuiWindowFlags_NoMove,且Docking功能已正确启用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:15:44