菜单

窗口和布局系统

相关源文件

本文档介绍了 Dear ImGui 的窗口管理和布局系统,详细说明了窗口如何创建、定位和调整大小,以及 UI 元素在窗口内的定位方式。有关可以放置在窗口中的特定控件的信息,请参阅 Widgets System

窗口基础知识

Dear ImGui 的 UI 构建于窗口这一概念之上,窗口是包含控件、内容和其他 UI 元素的矩形区域。窗口是组织 UI 的主要容器。

窗口架构

来源:imgui_internal.h imgui.cpp

窗口创建与生命周期

Dear ImGui 中的窗口遵循简单的 Begin/End 模式。

每个窗口都有一个由其标题派生的唯一标识符。窗口的存在与您应用程序的帧循环中的 Begin()/End() 调用绑定。如果您在给定帧中未调用窗口的 Begin(),则该窗口在该帧中不存在。

来源:imgui.cpp

窗口标志

可以通过传递给 Begin() 函数的各种标志来定制窗口。这些标志控制外观、行为和功能。

标志描述
ImGuiWindowFlags_NoTitleBar移除标题栏
ImGuiWindowFlags_NoResize禁用调整大小
ImGuiWindowFlags_NoMove禁用移动
ImGuiWindowFlags_NoScrollbar隐藏滚动条
ImGuiWindowFlags_NoCollapse禁用折叠按钮
ImGuiWindowFlags_AlwaysAutoResize每帧自动调整大小以适应内容
ImGuiWindowFlags_NoBackground禁用背景颜色/纹理
ImGuiWindowFlags_MenuBar启用菜单栏
ImGuiWindowFlags_NoSavedSettings阻止将窗口状态保存到 .ini 文件

来源:imgui.h

子窗口

子窗口是在另一个父窗口内嵌套的窗口。它们提供额外的组织能力,并可以有自己的滚动行为。

子窗口特别适用于在父窗口内创建可滚动区域。

自 ImGui 1.90(2023 年)以来,子窗口使用专用的标志,独立于窗口标志。

标志描述
ImGuiChildFlags_Border在子窗口周围显示边框
ImGuiChildFlags_AlwaysUseWindowPadding始终应用父窗口的内边距
ImGuiChildFlags_ResizeX启用沿 X 轴的调整大小
ImGuiChildFlags_ResizeY启用沿 Y 轴的调整大小
ImGuiChildFlags_AutoResizeX自动调整宽度以适应内容
ImGuiChildFlags_AutoResizeY自动调整高度以适应内容
ImGuiChildFlags_AlwaysAutoResize双轴自动调整大小

来源:imgui.h imgui.cpp

窗口定位和尺寸调整

窗口坐标系统

Dear ImGui 使用多个重要的坐标系统,理解它们很重要。

来源:imgui.cpp

最重要的与坐标相关的函数包括:

来源:imgui.h imgui.cpp

设置窗口位置和大小

您可以使用这些函数来控制窗口的定位和尺寸调整。

ImGuiCond_ 标志控制何时应用位置/大小。

条件描述
ImGuiCond_Always总是应用
ImGuiCond_Once仅应用一次
ImGuiCond_FirstUseEver仅当窗口不存在于 .ini 文件时应用
ImGuiCond_Appearing仅当窗口出现时应用

来源:imgui.h imgui.cpp

布局系统

Dear ImGui 中的布局系统决定了控件在窗口内的定位方式。它是基于光标的,随着控件的添加,光标会向前移动。

布局流程

来源:imgui.cpp

基本的布局流程是垂直的——每个控件都放置在前一个控件下方。但是,您可以修改此流程。

来源:imgui.h imgui.cpp

布局函数

布局系统提供了各种函数来控制控件的定位。

功能描述
SameLine()将下一个控件放在同一行
NewLine()强制换行
Spacing()添加垂直间距
Dummy()添加指定大小的空白区域
Indent()水平缩进内容
Unindent()移除水平缩进
BeginGroup()/EndGroup()将控件组合在一起
AlignTextToFramePadding()垂直对齐即将出现的文本

来源:imgui.h imgui.cpp

内容区域和工作区域

内容区域是窗口内边距中可以放置控件的区域。处理内容区域的关键函数:

来源:imgui.h imgui.cpp

布局和控件尺寸调整

Dear ImGui 中的控件具有以下尺寸行为:

  1. 固定尺寸 - 显式指定的尺寸。
  2. 内容尺寸 - 根据内容调整大小。
  3. 可用宽度 - 扩展以填充可用宽度。
  4. 可用高度 - 扩展以填充可用高度。

您可以使用以下方式控制控件的宽度:

来源:imgui.h imgui.cpp

高级布局功能

列提供了水平组织内容的方式。

自 ImGui 1.52 起,Tables 提供了一个比 columns 更强大的替代方案,具有更多附加功能。

来源:imgui.h imgui.cpp

分组任务

组允许将多个控件视为单个单元。

组对于以下用途很有用:

  • 在视觉上将控件保持在一起。
  • 获取多个控件的边界框。
  • 创建复杂的布局。

来源:imgui.h imgui.cpp

滚动和裁剪

窗口滚动

当内容超出窗口大小时,窗口会自动添加滚动条。您可以以编程方式控制滚动。

来源:imgui.h imgui.cpp

裁剪

Dear ImGui 会自动处理裁剪。超出可见区域的内容不会被渲染。

裁剪系统是一项重要的优化。超出可见区域的项目不会被渲染,从而节省性能。

来源:imgui_internal.h imgui.cpp

与其他系统的关系

窗口和布局系统与许多其他 ImGui 系统交互。

来源:imgui.cpp imgui_internal.h

最佳实践

  1. 窗口 ID:窗口 ID 是从窗口名称生成的——使用 ### 来自定义 ID,同时保留显示文本(例如,"My Window###UniqueID")。

  2. 子窗口与组:

    • 当您需要独立的滚动或独立的视觉容器时,请使用子窗口。
    • 当您需要将多个控件视为一个单元而无需视觉分隔时,请使用组。
  3. 调整窗口大小:

    • 对于固定大小的窗口,请使用 SetNextWindowSize() 配合 ImGuiCond_FirstUseEver 来允许用户调整大小。
    • 对于基于内容的尺寸调整,请使用 ImGuiWindowFlags_AlwaysAutoResize
  4. 布局效率:

    • GetContentRegionAvail() 对于创建适应可用空间的控件很有用。
    • 使用 SameLine()Dummy() 来实现精确的布局控制。

来源:imgui.cpp imgui_demo.cpp

结论

窗口和布局系统是 Dear ImGui 用户界面的基础。理解窗口如何创建、调整大小和定位,以及控件如何在其中流动,对于使用 Dear ImGui 创建有效的 UI 至关重要。

从使用 Begin()/End() 创建主窗口到使用 BeginChild()/EndChild() 创建子窗口,从基本的垂直布局到高级的基于列的设计,窗口和布局系统提供了将 UI 整合在一起的结构。