使用C++构建桌面应用程序,寻找一个合适的Gui框架是棘手的,尽管有很多其他的方法,例如:QT,Wx_Widgets等,但相比于它们,我更喜欢使用ImGui来进行构建应用程序。
在开始前,我们要知道ImGui是什么。
ImGui是一个轻量级、跨平台的图形界面库,不同于Qt、WPF等“保留模式”GUI,ImGui更适合动态、实时场景,值得注意的是ImGui中所有控件都是自绘的,不调用系统UI(如Windows按钮)。
那我们应该如何使用它来构建应用程序呢?
首先我们先准备项目目录。
例如:项目名为ImGuiGLFW,其中创建三个子文件夹build/(其中放项目构建时产生的中间文件),libs/(其中放和imgui,glfw等相关的源文件),src/(自己编写的源文件);由于使用CMake进行项目构建,因此还有新建一个CMakeLists文件。如下图所示:
要使用ImGui,需要一些必备的东西,以下是需要下载的源码及其网址:
网址 | 位置 | |
---|---|---|
Dear ImGui 源码 | https://github.com/ocornut/imgui/archive/refs/heads/master.zip | 根目录中的cpp和h文件以及backends/文件夹放入 libs/imgui/ 中 |
GLFW Windows 预编译 | https://www.glfw.org/download.html → 64-bit binaries | 解压压缩包,将include/ 和 lib-vc2022/ 放入 libs/glfw/ 中 |
glad OpenGL 加载器 | https://glad.dav1d.de/ 选 gl3.3Core + Generate&download | 解压文件,将 include/ 与 src/ 放入 libs/glad/ 中 |
工作做完之后 libs/ 类似于以下这种结构:
libs/ ├─ imgui/ │ ├─ *.cpp *.h │ └─ backends/ │ ├─ imgui_impl_glfw.cpp │ ├─ imgui_impl_glfw.h │ ├─ imgui_impl_opengl3.cpp │ └─ imgui_impl_opengl3.h ├─ glfw/ │ ├─ include/ │ └─ lib-vc2022/glfw3.lib └─ glad/ ├─ include/ └─ src/glad.c
为了测试方便,编写一个最小的可用的main函数放在 /src/main.cpp 中。
C++// 1) 必须放在最前面
#include <glad/glad.h>
// 2) 然后是 GLFW
#include <GLFW/glfw3.h>
// 3) 其余标准库 / ImGui
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <cstdio>
#include <cstdlib>
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}
int main(int, char**)
{
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) return 1;
const char* glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3", nullptr, nullptr);
if (!window) return 1;
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // 开启垂直同步
// 初始化 GLAD(或 gladLoadGLLoader)
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
return -1;
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
ImVec4 clear_color(0.45f, 0.55f, 0.60f, 1.00f);
while (!glfwWindowShouldClose(window) {
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::Begin("Hello, world");
ImGui::Text("This is a minimal ImGui+GLFW+OpenGL3 program.");
if (ImGui::Button("Press me"))
puts("Button pressed!");
ImGui::End();
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
这个函数会展示一个名为Hello, world
的窗口,其中有一个按钮,按下后打印Press me
。
在根目录下新建CMakeLists.txt文件,添加以下内容:
CMakeLists.txtcmake_minimum_required(VERSION 3.15) project(ImGuiGLFW) set(CMAKE_CXX_STANDARD 17) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # 包含路径 include_directories( libs/imgui libs/imgui/backends libs/glfw/include libs/glad/include ) # ImGui 源码 set(IMGUI_DIR libs/imgui) add_library(imgui STATIC ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp ${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp ) # glad add_library(glad STATIC libs/glad/src/glad.c) # 可执行文件 add_executable(${PROJECT_NAME} src/main.cpp) target_link_libraries(${PROJECT_NAME} imgui glad opengl32 ${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw/lib-vc2022/glfw3.lib )
//
当所有的文件都准备好以后,就可以进行项目的编译了。
打开终端,进入项目目录,依次输入以下内容:
bashcmake -B build -G "Visual Studio 17 2022"
cmake --build build --config Release
当如下所示时,代表完成:
这是我们可以在 /build/bin/Release/ 中找到可执行文件 ImGuiGLFW.exe 。
找到 ImGuiGLFW.exe ,双击运行便可以看到界面窗口。
至此,我们便使用ImGui构建了一个简单的GUI应用程序。
本文作者:流浪的将军
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!