ImGui: 一套C++ 即时模式 GUI(Immediate Mode GUI,IMGUI) 开源库
目录1.简介2.安装与集成3.源码文件架构4.标准集成流程5.核心常用控件与布局 API6.渲染底层原理7.完整示例8.生态扩展库9.优缺点10.常见使用场景1.简介Dear ImGui简称 ImGui是一套C 即时模式 GUIImmediate Mode GUIIMGUI开源库作者 Omar Cornut主打游戏、渲染引擎、仿真工具、调试面板开发。无强依赖仅标准 C不自带窗口 / 图形 API通过后端对接 OpenGL/DX11/Vulkan/GLFW/SDL定位编辑器、调试面板、工具 UI不适合商业桌面客户端Qt/MFC 场景。即时模式 vs 传统保留模式 GUI保留模式Qt、Win32、UE 原生 UI提前创建控件对象、长期保存在内存通过事件回调响应交互控件有独立生命周期。 缺点代码割裂、大量回调、工具类界面开发繁琐。即时模式ImGui 核心设计每一帧完整重绘全部 UI不长期存储控件对象UI 逻辑和业务逻辑写在同一段代码里。 单帧标准流程ImGui::NewFrame()开启新帧重置布局与输入状态顺序执行所有 UI 代码按钮、输入框、窗口交互同步修改你自己定义的变量无回调ImGui::Render()生成绘制命令数据图形后端渲染顶点到屏幕状态勾选框、输入文字、滑动条数值全部由外部变量保存ImGui 仅临时缓存布局、绘制数据帧结束全部丢弃。优势开发速度极快、逻辑直观调试工具首选短板超大数量控件上万性能弱于保留式 GUI。2.安装与集成1.获取 ImGui 源码https://github.com/ocornut/imguigit clone https://github.com/ocornut/imgui.git cd imgui # 稳定版本不要直接拉master git checkout docking下载压缩包官网 releaseshttps://github.com/ocornut/imgui/releases解压后得到imgui文件夹。2.提取项目必需文件只复制这些精简体积核心内核必须imgui/ ├─ imgui.h ├─ imgui.cpp ├─ imgui_draw.cpp ├─ imgui_widgets.cpp └─ imgui_tables.cpp后端绑定二选一组合后端分为「平台输入后端」「图形渲染后端」成对使用A.跨平台 GLFW OpenGL3最通用backends/imgui_impl_glfw.h/cpp backends/imgui_impl_opengl3.h/cppB.Windows 原生 Win32 DirectX11backends/imgui_impl_win32.h/cpp backends/imgui_impl_dx11.h/cpp扩展可选图表 ImPlot, 单独克隆 ImPlot 放到同级目录https://github.com/epezent/implotgit clone https://github.com/epezent/implot.git需要文件implot.h / implot.cpp / implot_items.cpp3.vcpkg安装安装 vcpkg 后执行安装命令# 基础imguiglfwopengl后端 vcpkg install imgui[glfw-binding,opengl3-binding] # 带ImPlot图表 vcpkg install imgui[glfw-binding,opengl3-binding,implot]VS 直接集成无需配置头文件 / 源码直接#include imgui.h4.CMake 项目集成配置跨平台 Linux/Windows/Mac基础 CMakeLists.txtGLFWOpenGLcmake_minimum_required(VERSION 3.16) project(ImGuiProject) set(CMAKE_CXX_STANDARD 17) # 1. 依赖 GLFW OpenGL find_package(glfw3 REQUIRED) find_package(OpenGL REQUIRED) # 2. ImGui 文件集合 set(IMGUI_ROOT ${CMAKE_SOURCE_DIR}/thirdparty/imgui) set(IMGUI_SRC ${IMGUI_ROOT}/imgui.cpp ${IMGUI_ROOT}/imgui_draw.cpp ${IMGUI_ROOT}/imgui_widgets.cpp ${IMGUI_ROOT}/imgui_tables.cpp # GLFW OpenGL后端 ${IMGUI_ROOT}/backends/imgui_impl_glfw.cpp ${IMGUI_ROOT}/backends/imgui_impl_opengl3.cpp ) # 3. 可选 ImPlot set(IMPLOT_ROOT ${CMAKE_SOURCE_DIR}/thirdparty/implot) set(IMPLOT_SRC ${IMPLOT_ROOT}/implot.cpp ${IMPLOT_ROOT}/implot_items.cpp ) # 编译目标 add_executable(App main.cpp ${IMGUI_SRC} ${IMPLOT_SRC}) # 头文件搜索路径 target_include_directories(App PRIVATE ${IMGUI_ROOT} ${IMGUI_ROOT}/backends ${IMPLOT_ROOT} ${OPENGL_INCLUDE_DIR} ) # 链接系统库 target_link_libraries(App PRIVATE glfw OpenGL::GL)3.源码文件架构核心内核文件文件作用imgui.h / imgui.cpp全局上下文、IO、窗口管理、主逻辑imgui_widgets.cpp所有内置控件按钮、输入框、表格实现imgui_draw.cpp顶点生成、线条、文字、图片渲染逻辑imgui_tables.cpp新版表格布局系统替代旧 Columns后端绑定目录backends/分为两类后端必须成对搭配使用平台后端处理窗口、鼠标键盘输入、剪贴板glfw,sdl2,win32渲染后端对接图形 API绘制顶点缓冲opengl3,dx11,dx12,vulkan扩展目录misc/字体加载、图标集成、修复补丁、文件对话框辅助工具。关键顶层数据结构ImGuiContext全局 UI 上下文存储所有窗口、布局、临时状态支持多实例多隔离 UI 环境单上下文只能单线程渲染。ImGuiIO输入与全局配置总入口窗口分辨率、鼠标 / 键盘数据、按键映射、全局开关 Flag、剪贴板、字体。ImGuiStyleUI 样式圆角、间距、内边距、全套颜色配置。ImDrawData / ImDrawList渲染输出核心每帧Render()生成ImDrawData包含多个绘制列表列表存储顶点、索引、绘制指令矩形、文字、贴图后端遍历绘制。4.标准集成流程1.初始化阶段// 1. 创建UI上下文 ImGui::CreateContext(); ImGuiIO io ImGui::GetIO(); // 2. 全局开关配置停靠、多视口等 io.ConfigFlags | ImGuiConfigFlags_DockingEnable; // 窗口停靠 io.ConfigFlags | ImGuiConfigFlags_ViewportsEnable; // 独立系统窗口 // 3. 加载字体中文、图标 io.Fonts-AddFontFromFileTTF(msyh.ttc, 16, nullptr, io.Fonts-GetGlyphRangesChineseFull()); // 4. 初始化平台渲染后端例GLFWOpenGL3 ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(#version 330); // 5. 修改默认样式 ImGui::StyleColorsDark(); ImGuiStyle style ImGui::GetStyle(); style.WindowRounding 6.0f;2.主渲染循环每帧固定顺序while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // 1. 后端同步输入给ImGuiIO鼠标、键盘、窗口尺寸 ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); // 开启新帧 // 你的所有UI绘制代码写在这里 ImGui::ShowDemoWindow(); // 官方Demo查看全部控件用法 bool open true; if (ImGui::Begin(调试面板, open)) { static float value 0.0f; ImGui::DragFloat(参数, value, 0.1f, 0, 100); if (ImGui::Button(执行)) { // 按钮点击逻辑直接写在这里无需回调 } } ImGui::End(); // // 2. 生成绘制数据 ImGui::Render(); // 3. 清空屏幕后端渲染UI glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // 多视口支持窗口拖出主窗口 if (io.ConfigFlags ImGuiConfigFlags_ViewportsEnable) { GLFWwindow* backup_current_context glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwMakeContextCurrent(backup_current_context); } glfwSwapBuffers(window); }3.程序退出销毁ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext();5.核心常用控件与布局 API1.窗口容器// 基础窗口open 控制右上角关闭叉号 ImGui::Begin(窗口名称, bool_open); ImGui::End(); // 内嵌滚动子窗口 ImGui::BeginChild(子面板, ImVec2(300, 200)); ImGui::EndChild(); // 模态弹窗阻塞交互 if (ImGui::BeginPopupModal(提示框)) { ImGui::Text(弹窗内容); if (ImGui::Button(关闭)) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); }2.交互控件// 按钮 if (ImGui::Button(按钮)) {} ImGui::SmallButton(小按钮); // 勾选框 static bool enable false; ImGui::Checkbox(启用, enable); // 单选框 static int sel 0; ImGui::RadioButton(选项A, sel, 0); ImGui::RadioButton(选项B, sel, 1); // 数值输入/拖拽/滑动条 static float f 1.0f; ImGui::DragFloat(数值, f, 0.01f, 0, 10); ImGui::SliderFloat(滑块, f, 0, 10); // 文本输入 char buf[128] 测试; ImGui::InputText(单行输入, buf, IM_ARRAYSIZE(buf)); ImGui::InputTextMultiline(多行, buf, ImVec2(200, 80)); // 折叠分组 if (ImGui::CollapsingHeader(折叠分组)) { ImGui::Text(内部内容); }3.布局控制高频必备ImGui::SameLine(20); // 下一个控件和上一行同行偏移20像素 ImGui::NewLine(); // 强制换行 ImGui::Spacing(); // 空一行间距 ImGui::Separator(); // 水平分割线 ImGui::Indent(); // 缩进 ImGui::Unindent(); // 取消缩进 // 预先设置下一个窗口位置/大小 ImGui::SetNextWindowPos(ImVec2(10,10)); ImGui::SetNextWindowSize(ImVec2(400,300));4.表格布局新版标准替代 Columns// 创建3列表格自适应宽度 if (ImGui::BeginTable(table, 3, ImGuiTableFlags_Borders)) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text(姓名); ImGui::TableNextColumn(); ImGui::Text(年龄); ImGui::TableNextColumn(); ImGui::Text(操作); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text(张三); ImGui::TableNextColumn(); ImGui::Text(24); ImGui::TableNextColumn(); ImGui::Button(编辑); ImGui::EndTable(); }5.底层绘图原语自定义绘制ImDrawList* draw ImGui::GetWindowDrawList(); ImVec2 pMin ImGui::GetCursorScreenPos(); ImVec2 pMax ImVec2(pMin.x 100, pMin.y 60); draw-AddRectFilled(pMin, pMax, IM_COL32(50,50,180,255)); // 填充矩形 draw-AddLine(pMin, pMax, IM_COL32_WHITE); // 直线 draw-AddText(pMin, IM_COL32_WHITE, 自定义绘制);6.右键菜单// 右键点击控件弹出菜单 if (ImGui::BeginPopupContextItem(右键菜单)) { if (ImGui::MenuItem(复制)) {} if (ImGui::MenuItem(删除)) {} ImGui::EndPopup(); }6.渲染底层原理NewFrame 阶段读取鼠标、键盘、窗口尺寸输入重置布局计算器计算所有窗口 Hover、焦点、滚动状态。UI 构建阶段执行你写的所有控件代码实时计算每个控件宽高、屏幕坐标直接写入顶点缓存同步检测点击、拖拽、输入修改外部变量。Render 阶段裁剪窗口、合并绘制指令打包成ImDrawData所有文字转为字体图集 UV 坐标生成三角形顶点。后端绘制阶段遍历绘制列表绑定顶点缓冲、字体纹理批量提交绘制尽可能减少渲染批次DrawCall。字体渲染机制ImGui 使用单张图集纹理存储全部字符支持加载 TTF 自定义字体追加中文字符范围合并图标字体FontAwesome实现按钮图标全局切换字体大小。7.完整示例功能中文支持、窗口停靠、基础控件、表格、自定义绘图、右键菜单、弹窗#include glad/glad.h #include GLFW/glfw3.h #include imgui.h #include imgui_impl_glfw.h #include imgui_impl_opengl3.h #include cstdio #include vector // 全局UI数据 static float g_float_val 50.0f; static bool g_check_enable false; static int g_radio_sel 0; static char g_input_buf[256] 测试中文输入; static bool show_demo_window true; static bool show_custom_window true; int main() { // 1. GLFW 窗口初始化 glfwInit(); const char* glsl_version #version 330; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); GLFWwindow* window glfwCreateWindow(1280, 720, ImGui 完整Demo, nullptr, nullptr); glfwMakeContextCurrent(window); glfwSwapInterval(1); // 开启垂直同步 // 2. ImGui 上下文创建 ImGui::CreateContext(); ImGuiIO io ImGui::GetIO(); io.IniFilename ui_layout.ini; // 自动保存窗口布局 // 开启停靠、多视口 io.ConfigFlags | ImGuiConfigFlags_DockingEnable; io.ConfigFlags | ImGuiConfigFlags_ViewportsEnable; // 加载中文字体fonts/msyh.ttc ImFontConfig font_cfg; font_cfg.GlyphMinAdvanceX 14.0f; static const ImWchar chinese_ranges[] { 0x4E00, 0x9FFF, // 中文汉字区间 0 }; io.Fonts-AddFontFromFileTTF(./fonts/msyh.ttc, 16.0f, font_cfg, chinese_ranges); io.Fonts-Build(); // 样式设置 ImGui::StyleColorsDark(); ImGuiStyle style ImGui::GetStyle(); if (io.ConfigFlags ImGuiConfigFlags_ViewportsEnable) { style.WindowRounding 0.0f; style.Colors[ImGuiCol_WindowBg].w 1.0f; } style.WindowRounding 6.0f; style.ItemSpacing ImVec2(8, 6); // 3. 绑定GLFWOpenGL后端 ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); // 主渲染循环 while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // ImGui帧启动 ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); // UI绘制区域 // 1. 官方示例窗口查看全部控件用法 if (show_demo_window) ImGui::ShowDemoWindow(show_demo_window); // 2. 全局停靠空间 ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); // 3. 自定义窗口 if (show_custom_window) { ImGui::Begin(自定义调试面板, show_custom_window, ImGuiWindowFlags_MenuBar); // 菜单栏 if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu(菜单)) { if (ImGui::MenuItem(弹出弹窗)) ImGui::OpenPopup(提示弹窗); ImGui::MenuItem(关闭窗口, nullptr, show_custom_window); ImGui::EndMenu(); } ImGui::EndMenuBar(); } // 基础交互控件 ImGui::Text(基础交互控件); ImGui::DragFloat(浮点参数, g_float_val, 0.5f, 0.0f, 100.0f); ImGui::SliderFloat(滑动条, g_float_val, 0, 100); ImGui::Checkbox(启用功能, g_check_enable); ImGui::Text(单选选择); ImGui::RadioButton(选项一, g_radio_sel, 0); ImGui::SameLine(); ImGui::RadioButton(选项二, g_radio_sel, 1); ImGui::SameLine(); ImGui::RadioButton(选项三, g_radio_sel, 2); ImGui::InputText(单行输入框, g_input_buf, IM_ARRAYSIZE(g_input_buf)); if (ImGui::Button(点击按钮)) { printf(按钮被点击当前数值%.2f\n, g_float_val); } ImGui::SameLine(); ImGui::SmallButton(小按钮); ImGui::Separator(); ImGui::Text(表格布局示例); // 3列表格 if (ImGui::BeginTable(table_demo, 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn(姓名); ImGui::TableSetupColumn(数值); ImGui::TableSetupColumn(操作); ImGui::TableHeadersRow(); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text(测试用户); ImGui::TableNextColumn(); ImGui::Text(%.2f, g_float_val); ImGui::TableNextColumn(); if (ImGui::Button(重置)) g_float_val 0; ImGui::EndTable(); } ImGui::Separator(); ImGui::Text(自定义绘制图形); ImDrawList* draw ImGui::GetWindowDrawList(); ImVec2 cursor ImGui::GetCursorScreenPos(); ImVec2 rect_max ImVec2(cursor.x 120, cursor.y 60); draw-AddRectFilled(cursor, rect_max, IM_COL32(40, 120, 220, 180)); draw-AddRect(cursor, rect_max, IM_COL32_WHITE, 4.0f); draw-AddText(ImVec2(cursor.x 10, cursor.y 20), IM_COL32_WHITE, 自定义矩形); ImGui::SetCursorScreenPos(ImVec2(rect_max.x 10, cursor.y)); // 右键菜单 if (ImGui::BeginPopupContextItem(右键菜单)) { ImGui::MenuItem(复制); ImGui::MenuItem(粘贴); ImGui::MenuItem(清空); ImGui::EndPopup(); } ImGui::End(); } // 模态弹窗 if (ImGui::BeginPopupModal(提示弹窗, nullptr, ImVec2(300, 150))) { ImGui::Text(这是模态弹窗阻塞其他交互); ImGui::Spacing(); if (ImGui::Button(关闭, ImVec2(100, 30))) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); } // // 渲染提交 ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, display_w, display_h); glViewport(0, 0, display_w, display_h); glClearColor(0.1f, 0.1f, 0.12f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 绘制UI ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // 多视口支持 if (io.ConfigFlags ImGuiConfigFlags_ViewportsEnable) { GLFWwindow* backup glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwMakeContextCurrent(backup); } glfwSwapBuffers(window); } // 释放资源 ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; }8.生态扩展库ImPlot实时曲线图、直方图、性能监控图表调试性能首选ImNodes节点编辑器材质蓝图、流程编辑器ImGuiColorTextEdit带语法高亮代码编辑器ImFileDialog跨平台文件打开 / 保存对话框FontAwesome图标字体给按钮添加图标ImSpinner加载动画、进度控件。9.优缺点优势集成简单无复杂依赖嵌入自制引擎、模拟器零成本即时模式开发效率极高UI 与业务代码合一无回调完整内置编辑器功能停靠、表格、弹窗、拖拽跨全平台Windows/Linux/macOS/ 安卓 /iOS自带完整 Demo一键查看所有控件用法底层绘图接口开放可任意自定义控件。劣势每帧重建 UI上万控件场景性能远弱于 Qt无原生系统控件无障碍、系统主题支持差不适合商业桌面软件中文需手动加载字体默认不支持中文同一 UI 上下文只能单线程渲染多线程易崩溃无组件生命周期复杂界面需要手动封装复用。10.常见使用场景游戏引擎调试面板、内置编辑器图形渲染工具、离线仿真、军事仿真控制面板性能监控工具帧率、内存、渲染管线参数调节建模、材质、动画小型工具软件模拟器、工控调试程序