【C++】ImGui:极简化的立即模式GUI开发
如果你是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(glfwGIT_REPOSITORY https://github.com/glfw/glfwGIT_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(imguiGIT_REPOSITORY https://github.com/ocornut/imguiGIT_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);// 初始化 ImGuiIMGUI_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的强大功能。祝你学习愉快!
相关文章:
【C++】ImGui:极简化的立即模式GUI开发
如果你是GUI开发的新手,或想试试轻量级、易集成的GUI库,ImGui(即时模式图形用户界面)是个不错的选择。它以简洁的API、跨平台的兼容性和卓越的性能,受到许多开发者的喜爱。无论是为C项目添加调试界面,还是构…...
5G学习笔记之BWP
我们只会经历一种人生,我们选择的人生。 参考:《5G NR标准》、《5G无线系统指南:如微见著,赋能数字化时代》 目录 1. 概述2. BWP频域位置3. 初始与专用BWP4. 默认BWP5. 切换BWP 1. 概述 在LTE的设计中,默认所有终端均能处理最大2…...
1. 搭建前端+后端开发框架
1. 说明 本篇博客主要介绍网页开发中,搭建前端和后端开发框架的具体步骤,框架中所使用的技术栈如下: 前端:VUE Javascript 后端:Python Flask Mysql 其中MySQL主要用来存储需要的数据,在本文中搭建基本…...
深入浅出:插入排序算法完全解析
1. 什么是插入排序? 插入排序(Insertion Sort)是一种简单的排序算法,其基本思想与我们整理扑克牌的方式非常相似。我们将扑克牌从第二张开始依次与前面已排序的牌进行比较,将其插入到合适的位置,直到所有牌…...
(十一)基于vue3+mapbox-GL实现模拟高德实时导航轨迹播放
要在 Vue 3 项目中结合 Mapbox GL 实现类似高德地图的实时导航轨迹功能,您可以按照以下步骤进行: 安装依赖: 首先,安装 mapbox-gl 和 @turf/turf 这两个必要的库: npm install mapbox-gl @turf/turf引入 Mapbox GL: 在组件中引入 mapbox-gl 并初始化地图实例: <templ…...
DeepSeek到TinyLSTM的知识蒸馏
一、架构设计与适配 模型结构对比: DeepSeek(教师模型):基于Transformer,多头自注意力机制,层数≥12,隐藏层维度≥768TinyLSTM(学生模型):单层双向LSTM&#…...
【Transformer模型学习】第三篇:位置编码
文章目录 0. 前言1. 为什么需要位置编码?2. 如何进行位置编码?3. 正弦和余弦位置编码4. 举个例子4.1 参数设置4.2 计算分母项4.3 计算位置编码4.4 位置编码矩阵 5. 相对位置信息6. 改进的位置编码方式——RoPE6.1 RoPE的核心思想6.2 RoPE的优势 7. 总结 …...
微信小程序自定义导航栏实现指南
文章目录 微信小程序自定义导航栏实现指南一、自定义导航栏的需求分析二、代码实现1. WXML 结构2. WXSS 样式样式解析:3. JavaScript 逻辑三、完整代码示例四、注意事项与优化建议五、总结微信小程序自定义导航栏实现指南 在微信小程序开发中,默认的导航栏样式可能无法满足所…...
(十 六)趣学设计模式 之 责任链模式!
目录 一、 啥是责任链模式?二、 为什么要用责任链模式?三、 责任链模式的实现方式四、 责任链模式的优缺点五、 责任链模式的应用场景六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,…...
20250225-代码笔记03-class CVRPModel AND other class
文章目录 前言一、class CVRPModel(nn.Module):__init__(self, **model_params)函数功能函数代码 二、class CVRPModel(nn.Module):pre_forward(self, reset_state)函数功能函数代码 三、class CVRPModel(nn.Module):forward(self, state)函数功能函数代码 四、def _get_encodi…...
面试常问的压力测试问题
性能测试作为软件开发中的关键环节,确保系统在高负载下仍能高效运行。压力测试作为性能测试的重要类型,旨在通过施加超出正常负载的压力,观察系统在极端条件下的表现。面试中,相关问题常被问及,包括定义、重要性、与负…...
Python——365天学习规划
文章目录 1. 第一阶段:Python基础(Day 1-60) 1.1 Week 1-2:基础语法 1.1.1 Day 1-3:变量、数据类型、运算符、输入输出 1.1.2 Day 4-7:条件语句(if-elif-else) 1.1.3 Day 8-14&…...
河南理工XCPC萌新选拔赛
A 树之荣荣 青梅熙熙 树之荣荣 青梅熙熙 这个题是一个经典的博弈问题。我们可以考虑一种情况,就是你每一次都会取一个。那么最后一个你肯定不能取。所以我们可以考虑减去一个后的值。判断它的和是奇数还是偶数即可。 int n; cin >> n;int s 0;for (int i 1;…...
设计模式|策略模式 Strategy Pattern 详解
目录 一、策略模式概述二、策略模式的实现2.1 策略接口2.2 具体策略类2.3 上下文类2.4 客户端代码2.5 UML类图2.6 UML时序图 三、优缺点3.1 ✅优点3.2 ❌ 缺点 四、最佳实践场景4.1 适合场景描述4.2 具体场景 五、扩展5.1 继承复用机制和复合策略5.2 对象管理:优化策…...
Wireshark 插件开发实战指南
Wireshark 插件开发实战指南 环境搭建流程图 #mermaid-svg-XpNibno7BIyfzNn5 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XpNibno7BIyfzNn5 .error-icon{fill:#552222;}#mermaid-svg-XpNibno7BIyfzNn5 .error-t…...
使用Java构建高效的Web服务架构
使用Java构建高效的Web服务架构 随着互联网技术的飞速发展,Web服务在现代应用中扮演着至关重要的角色。尤其是在企业级应用中,如何构建一个高效、可扩展且易维护的Web服务架构,成为了开发者和架构师面临的一项重要挑战。Java作为一种成熟、稳…...
《Python实战进阶》No 10:基于Flask案例的Web 安全性:防止 SQL 注入、XSS 和 CSRF 攻击
第10集:Web 安全性:防止 SQL 注入、XSS 和 CSRF 攻击 在现代 Web 开发中,安全性是至关重要的。无论是用户数据的保护,还是系统稳定性的维护,开发者都需要对常见的 Web 安全威胁有深刻的理解,并采取有效的防…...
蓝桥备赛(六)- C/C++输入输出
一、OJ题目输入情况汇总 OJ(online judge) 接下来会有例题 , 根据一下题目 , 对这些情况进行分析 1.1 单组测试用例 单在 --> 程序运行一次 , 就处理一组 练习一:计算 (ab)/c 的值 B2009 计算 (ab)/c …...
企微审批中MySQL字段TEXT类型被截断的排查与修复实践
在MySQL中,TEXT类型字段常用于存储较大的文本数据,但在一些应用场景中,当文本内容较大时,TEXT类型字段可能无法满足需求,导致数据截断或插入失败。为了避免这种问题,了解不同文本类型(如TEXT、M…...
[ISP] AE 自动曝光
相机通过不同曝光参数(档位快门时间 x 感光度 x 光圈大小)控制进光量来完成恰当的曝光。 自动曝光流程大概分为三部分: 1. 测光:点测光、中心测光、全局测光等;通过调整曝光档位使sensor曝光在合理的阈值内࿰…...
小程序画带圆角的圆形进度条
老的API <canvas id"{{canvasId}}" canvas-id"{{canvasId}}" style"opacity: 0;" class"canvas"/> startDraw() {const { canvasId } this.dataconst query this.createSelectorQuery()query.select(#${canvasId}).bounding…...
16. LangChain实战项目2——易速鲜花内部问答系统
需求简介 易束鲜花企业内部知识库如下: 本实战项目设计一个内部问答系统,基于这些内部知识,回答内部员工的提问。 在前面课程的基础上,需要安装的依赖包如下: pip install docx2txt pip install qdrant-client pip i…...
代码的解读——自用
代码来自:https://github.com/ChuHan89/WSSS-Tissue?tabreadme-ov-file 借助了一些人工智能 run_pipeline.sh 功能总结 该脚本用于执行一个 弱监督语义分割(WSSS) 的完整流程,包含三个阶段: Stage1:训…...
蓝桥杯试题:DFS回溯
一、题目要求 输入一个数组n,输出1到n的全排列 二、代码展示 import java.util.*;public class ikun {static List<List<Integer>> list new ArrayList<>();public static void main(String[] args) { Scanner sc new Scanner(System.in);…...
FPGA开发,使用Deepseek V3还是R1(8):FPGA的全流程(简略版)
以下都是Deepseek生成的答案 FPGA开发,使用Deepseek V3还是R1(1):应用场景 FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别 FPGA开发,使用Deepseek V3还是R1&#x…...
一个py文件搞定mysql查询+Json转换+表数据提取+根据数据条件生成excel文件+打包运行一条龙
import os import argparse import pymssql import json import pandas as pd from datetime import datetime from pandas.io.formats.excel import ExcelFormatter import openpyxl# 投注类型映射字典 BET_MAPPING {1: WIN, 2: PLA, 3: QIN, 4: QPL,5: DBL, 6: TCE, 7: QTT,…...
微服务学习(1):RabbitMQ的安装与简单应用
目录 RabbitMQ是什么 为什么要使用RabbitMQ RabbitMQ的安装 RabbitMQ架构及其对应概念 队列的主要作用 交换机的主要作用 RabbitMQ的应用 通过控制面板操作(实现收发消息) RabbitMQ是什么 RabbitMQ是一个开源的消息队列软件(消息代理…...
【RAG】Embeding 和 Rerank学习笔记
Q: 现在主流Embeding模型架构 在RAG(Retrieval-Augmented Generation)系统中,嵌入模型(Embedding Model) 是检索阶段的核心组件,负责将查询(Query)和文档(Document&#…...
【Delphi】如何解决使用webView2时主界面置顶,而导致网页选择文件对话框被覆盖问题
一、问题描述: 在Delphi 中使用WebView2控件,如果预先把主界面置顶(Self.FormStyle : fsStayOnTop;),此时,如果在Web页面中有使用(<input type"file" id"fileInput" acc…...
【量化金融自学笔记】--开篇.基本术语及学习路径建议
在当今这个信息爆炸的时代,金融领域正经历着一场前所未有的变革。传统的金融分析方法逐渐被更加科学、精准的量化技术所取代。量化金融,这个曾经高不可攀的领域,如今正逐渐走进大众的视野。它将数学、统计学、计算机科学与金融学深度融合&…...
