如果你是GUI开发的新手,或想试试轻量级、易集成的GUI库,ImGui(即时模式图形用户界面)是个不错的选择。它以简洁的API、跨平台的兼容性和卓越的性能,受到许多开发者的喜爱。无论是为C++项目添加调试界面,还是构建完整应用,ImGui都能满足你的需求。
本教程将从零开始,帮助你了解ImGui的基本概念,学习如何设置开发环境,理解项目结构,并通过简单的示例项目掌握其使用方法。让我们开始吧!
什么是ImGui
ImGui是一个即时模式GUI库,这意味着它不需要像传统GUI库那样维护复杂的对象层次或事件循环。相反,ImGui允许你在每一帧中直接绘制和更新界面元素,这种方式非常直观,特别适合于游戏开发、工具开发和实时应用。
ImGui的优点:
- 轻量级:ImGui的代码库非常小,易于集成到现有项目中。
- 高性能:ImGui的设计使其在渲染大量界面元素时仍能保持流畅。
- 跨平台:ImGui支持Windows、macOS、Linux等多种操作系统。
- 易于使用:ImGui的API简单直观,学习曲线平缓。
- 高度可定制:你可以轻松地调整ImGui的样式和行为,以适应你的项目需求。
环境准备
在开始编写ImGui代码之前,你需要准备好以下开发环境和工具。请确保你已经安装了以下软件:
- C++编译器:本教程使用MinGW(Minimalist GNU for Windows)作为编译器,但你也可以使用其他支持C++17的编译器,如Visual Studio、Clang等。
- CMake:CMake是一个跨平台的构建工具,用于生成Makefile或项目文件,版本要求3.20或更高。
- Git:用于下载ImGui和GLFW的源代码。
- OpenGL:ImGui使用OpenGL进行渲染,因此你的系统需要支持OpenGL 3.0或更高版本。
- 文本编辑器或IDE:如Visual Studio Code、CLion、Sublime Text等,用于编写和编辑代码。
提示:本教程不会提供具体安装步骤,请根据你的操作系统和偏好,自行安装和配置上述工具。
项目结构
在开始编写代码之前,了解项目的文件组织方式非常重要。我们的示例项目结构非常简单,所有文件都平铺在项目根目录下:
my_imgui_project/
├── CMakeLists.txt
├── main.cpp
└── Application.hpp
- CMakeLists.txt:CMake配置文件,负责下载依赖库(如ImGui和GLFW)、配置编译选项和生成可执行文件。
- main.cpp:主程序文件,包含GLFW和ImGui的初始化、主循环和清理代码。
- Application.hpp:头文件,定义了ImGui界面的绘制逻辑。
这种平铺结构适合小型项目,易于管理和理解。
CMake配置
CMakeLists.txt是项目的核心配置文件,它告诉CMake如何构建项目。它的主要作用包括:
- 设置CMake最低版本和项目名称。
- 指定C++标准(本项目使用C++17)。
- 配置编译选项(如MinGW的静态链接)。
- 自动下载和集成GLFW和ImGui库。
- 生成可执行文件并链接必要的库(如OpenGL)。
具体的CMakeLists.txt内容请参考项目文件,这里我们只关注其作用:它简化了项目的构建过程,让你专注于代码编写。
# 设置最低 CMake 版本要求
cmake_minimum_required(VERSION 3.20)
# 定义项目名称
project(my_imgui_project)
# 设置 C++ 标准并强制要求
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 如果使用 MinGW,启用静态链接
if(MINGW)
add_link_options(-static -static-libgcc -static-libstdc++)
endif()
# 引入 FetchContent 模块
include(FetchContent)
# 下载并配置 GLFW(静态库)
FetchContent_Declare(
glfw
GIT_REPOSITORY https://github.com/glfw/glfw
GIT_TAG 3.3.8
)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(glfw)
# 下载并配置 ImGui
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG v1.89.9
)
FetchContent_MakeAvailable(imgui)
# 定义 ImGui 源文件并创建静态库
file(GLOB IMGUI_SOURCES
"${imgui_SOURCE_DIR}/*.cpp"
"${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp"
"${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp"
)
add_library(imgui STATIC ${IMGUI_SOURCES})
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends)
target_link_libraries(imgui PUBLIC glfw)
# 创建可执行文件,所有源文件平铺在根目录
add_executable(${PROJECT_NAME} WIN32 main.cpp)
# 链接库(Windows 下添加 gdi32 以确保兼容性)
target_link_libraries(${PROJECT_NAME} PRIVATE imgui glfw opengl32 $<$<PLATFORM_ID:Windows>:gdi32>)
代码解析
Application.hpp
Application.hpp
是项目的头文件,负责定义ImGui界面的绘制逻辑。它被包含在main.cpp
中,并在主循环中调用。
#pragma once
#include <imgui.h>
namespace app {
// Render 函数:负责绘制 ImGui 界面
inline void Render() {
// 开始一个新的 ImGui 窗口
ImGui::Begin("Made By Touken", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove);
// 获取当前窗口的大小
ImVec2 windowSize = ImGui::GetIO().DisplaySize;
// 设置窗口的大小和位置
ImGui::SetWindowSize(windowSize);
ImGui::SetWindowPos(ImVec2(0, 0));
// 显示一段简单的文本
ImGui::Text("This is a minimal ImGui application.");
// 结束当前窗口
ImGui::End();
}
}
代码解析:
#include <imgui.h>
:包含ImGui的头文件,提供ImGui的核心功能。namespace app
:使用命名空间封装代码,避免命名冲突。inline void Render()
:定义一个内联函数,负责绘制界面。ImGui::Begin("Hello, world!")
:创建一个标题为"Hello, world!"的窗口。ImGui::Text(...)
:在窗口中显示文本。ImGui::End()
:结束窗口的绘制。
这个文件展示了ImGui的核心思想:通过简单的函数调用快速构建界面。
main.cpp
main.cpp
是项目的入口文件,负责初始化GLFW和ImGui,运行主循环,并在程序结束时清理资源。
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <GLFW/glfw3.h>
#include "Application.hpp"
// 主函数,程序入口
int main() {
// 初始化 GLFW 库
if (!glfwInit()) {
return -1; // 初始化失败则退出
}
// 创建一个 1280x720 的窗口
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui GLFW OpenGL3 Example", nullptr, nullptr);
if (!window) {
glfwTerminate(); // 创建失败则清理并退出
return -1;
}
// 将当前窗口的 OpenGL 上下文设置为活动状态
glfwMakeContextCurrent(window);
// 初始化 ImGui
IMGUI_CHECKVERSION(); // 检查 ImGui 版本
ImGui::CreateContext(); // 创建 ImGui 上下文
ImGuiIO& io = ImGui::GetIO(); (void)io; // 获取 IO 对象
ImGui::StyleColorsDark(); // 设置暗色主题
ImGui_ImplGlfw_InitForOpenGL(window, true); // 初始化 GLFW 后端
ImGui_ImplOpenGL3_Init("#version 130"); // 初始化 OpenGL3 后端
// 主循环,直到窗口关闭
while (!glfwWindowShouldClose(window)) {
// 处理 GLFW 事件(如键盘、鼠标输入)
glfwPollEvents();
// 开始新的一帧
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 调用封装的 Render 函数绘制界面
app::Render();
// 渲染 ImGui 内容
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h); // 获取窗口大小
glViewport(0, 0, display_w, display_h); // 设置 OpenGL 视口
glClearColor(0.45f, 0.55f, 0.60f, 1.00f); // 设置背景颜色
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // 渲染 ImGui 数据
// 交换前后缓冲区,显示渲染结果
glfwSwapBuffers(window);
}
// 清理资源
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
代码解析:
- GLFW初始化:
glfwInit()
:初始化GLFW库。glfwCreateWindow()
:创建1280x720的窗口。glfwMakeContextCurrent()
:激活窗口的OpenGL上下文。
- ImGui初始化:
ImGui::CreateContext()
:创建ImGui上下文。ImGui::StyleColorsDark()
:设置暗色主题。ImGui_ImplGlfw_InitForOpenGL()
和ImGui_ImplOpenGL3_Init()
:初始化GLFW和OpenGL3后端。
- 主循环:
glfwPollEvents()
:处理用户输入事件。ImGui::NewFrame()
等:准备新的一帧。app::Render()
:绘制ImGui界面。glClear()
和ImGui_ImplOpenGL3_RenderDrawData()
:渲染界面到屏幕。glfwSwapBuffers()
:显示渲染结果。
- 清理:按顺序关闭ImGui和GLFW,释放资源。
构建和运行
要构建和运行项目,请按照以下步骤操作:
-
打开终端,进入项目根目录。
-
创建
build
文件夹并进入:
mkdir build
cd build
- 使用CMake生成Makefile:
cmake -G "MinGW Makefiles" ..
- 编译项目:
mingw32-make
- 运行可执行文件:
./my_imgui_project.exe
成功运行后,你将看到一个简单的ImGui窗口,显示"Hello, world!"和一段文本。
扩展和学习
你已经完成了ImGui的入门!接下来可以尝试:
- 在
Render()
中添加按钮、滑块等控件。 - 修改
ImGui::StyleColorsDark()
为其他样式。 - 响应用户输入,实现交互功能。
- 查看ImGui官方文档,学习更多高级用法。
通过实践和探索,你将逐渐掌握ImGui的强大功能。祝你学习愉快!