关注

ImGui: 一套C++ 即时模式 GUI(Immediate Mode GUI,IMGUI) 开源库

目录

1.简介

2.安装与集成

3.源码文件架构

4.标准集成流程

5.核心常用控件与布局 API

6.渲染底层原理

7.完整示例

8.生态扩展库

9.优缺点

10.常见使用场景


1.简介

        Dear ImGui(简称 ImGui)是一套C++ 即时模式 GUI(Immediate Mode GUI,IMGUI) 开源库,作者 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/imgui

git clone https://github.com/ocornut/imgui.git
cd imgui
# 稳定版本,不要直接拉master
git checkout docking

下载压缩包:

官网 releases:https://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/cpp

B.Windows 原生 Win32 + DirectX11

backends/imgui_impl_win32.h/cpp
backends/imgui_impl_dx11.h/cpp

扩展(可选,图表 ImPlot), 单独克隆 ImPlot 放到同级目录:

https://github.com/epezent/implot

git clone https://github.com/epezent/implot.git

需要文件:implot.h / implot.cpp / implot_items.cpp

3.vcpkg安装

安装 vcpkg 后执行安装命令

# 基础imgui+glfw+opengl后端
vcpkg install imgui[glfw-binding,opengl3-binding]
# 带ImPlot图表
vcpkg install imgui[glfw-binding,opengl3-binding,implot]

VS 直接集成,无需配置头文件 / 源码,直接 #include <imgui.h>

4.CMake 项目集成配置(跨平台 Linux/Windows/Mac)

基础 CMakeLists.txt(GLFW+OpenGL)

cmake_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、剪贴板、字体。
  • ImGuiStyle UI 样式:圆角、间距、内边距、全套颜色配置。
  • 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. 初始化平台+渲染后端(例:GLFW+OpenGL3)
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.核心常用控件与布局 API

1.窗口容器

// 基础窗口,&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. 绑定GLFW+OpenGL后端
    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.常见使用场景

  • 游戏引擎调试面板、内置编辑器;
  • 图形渲染工具、离线仿真、军事仿真控制面板;
  • 性能监控工具(帧率、内存、渲染管线参数调节);
  • 建模、材质、动画小型工具软件;
  • 模拟器、工控调试程序

转载自CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/haokan123456789/article/details/162349773

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--