golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用
Golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用
cimgui-go是一个为Dear ImGui生成Go语言绑定的项目,它提供了多个默认的后端实现,支持macOS(arm64/x86)、Windows(x64)和多种Linux发行版。
项目状态
模块概览
包名 | 描述 |
---|---|
imgui , implot , imnodes 等 |
Dear ImGui(及其插件)的实际绑定,用于显示控件和其他UI元素 |
examples |
展示如何使用cimgui-go的示例 |
cmd/codegen |
生成Go绑定的代码生成器 |
backend |
各种后端的抽象层(glfw, sdl, ebiten等) |
backend/* |
使用系统库渲染ImGui的特定后端实现 |
impl |
负责imgui与后端交互的包 |
支持的Backend
cimgui-go实现了几个imgui后端,都放在backend/
子包中:
- GLFW (GLFW 3.3 + OpenGL)
- SDL2 (SDL 2 + OpenGL)
- Ebitengine
重要提示:不同的解决方案使用不同的C库,可能会相互冲突。建议不要同时导入GLFW和SDL后端,可能会导致链接器崩溃。
完整示例Demo
下面是一个使用GLFW后端的完整示例代码:
package main
import (
"github.com/AllenDang/cimgui-go"
"github.com/AllenDang/cimgui-go/backend/glfwbackend"
"github.com/go-gl/glfw/v3.3/glfw"
)
func main() {
// 初始化GLFW
if err := glfw.Init(); err != nil {
panic(err)
}
defer glfw.Terminate()
// 创建窗口
window, err := glfw.CreateWindow(1280, 720, "cimgui-go GLFW example", nil, nil)
if err != nil {
panic(err)
}
// 创建imgui上下文
context := cimgui.CreateContext()
defer context.Destroy()
// 初始化GLFW后端
backend := glfwbackend.NewBackend(window)
backend.SetAfterCreateContextHook(func() {
// 设置imgui样式
style := cimgui.CurrentStyle()
style.ScaleAllSizes(1.5)
})
// 初始化imgui IO
io := cimgui.CurrentIO()
io.SetConfigFlags(io.ConfigFlags() | cimgui.ConfigFlagsNavEnableKeyboard)
// 主循环
for !window.ShouldClose() {
glfw.PollEvents()
// 开始新帧
backend.NewFrame()
cimgui.NewFrame()
// 创建imgui窗口和控件
cimgui.Begin("Hello, world!")
cimgui.Text("This is some useful text.")
if cimgui.Button("Click me!") {
// 按钮点击处理
cimgui.OpenPopup("Popup")
}
if cimgui.BeginPopup("Popup") {
cimgui.Text("You clicked the button!")
cimgui.EndPopup()
}
cimgui.End()
// 渲染
cimgui.Render()
backend.Render(cimgui.RenderedDrawData())
window.SwapBuffers()
}
}
命名约定
- 对于函数,'Im/ImGui/ig’前缀被移除
Get
前缀也被移除(有一些例外)- 如果函数来自
imgui_internal.h
,则添加Internal
前缀
指针和切片
在C中无法区分指针和切片,我们的代码默认为指针,但你可以通过&(slice[0])
轻松将切片转换为指针。
小技巧:utils
包中有一些实用函数:
utils.SliceToPtr(slice []T) *T
- 将切片转换为指针utils.PtrToSlice(ptr *T, size int) []T
- 将指针转换为给定大小的切片
回调函数
目前Go(1.24)不支持通过CGO将匿名函数传递给C。我们有一个解决方案-预生成大量全局函数和一个池。
应用截图
贡献指南
所有类型的贡献都受欢迎!但请注意:
警告:你永远不应该手动修改自动生成的文件!所有违反此规则的Pull Request都不会通过自动检查,也不会被合并。
当前解决方案是:
- 使用cimgui的lua生成器将函数和结构定义生成为json
- 通过手动编写的Go程序从定义生成正确的Go代码
- 使用imgui的后端实现
- 使用GitHub工作流编译cimgui、glfw和其他C依赖项为静态库
更多关于golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用cimgui-go进行Golang GUI开发
cimgui-go是Go语言对Dear ImGui的绑定库,允许你在Go中创建轻量级、高效的即时模式GUI界面。下面我将详细介绍如何使用这个库。
安装和基本设置
首先需要安装cimgui-go:
go get github.com/inkyblackness/imgui-go/v4
基本示例
下面是一个简单的使用cimgui-go创建窗口的示例:
package main
import (
"github.com/inkyblackness/imgui-go/v4"
"github.com/veandco/go-sdl2/sdl"
"github.com/veandco/go-sdl2/sdlrenderer"
)
func main() {
// 初始化SDL
if err := sdl.Init(sdl.INIT_VIDEO); err != nil {
panic(err)
}
defer sdl.Quit()
// 创建窗口
window, err := sdl.CreateWindow("cimgui-go示例",
sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
800, 600, sdl.WINDOW_OPENGL|sdl.WINDOW_RESIZABLE)
if err != nil {
panic(err)
}
defer window.Destroy()
// 创建渲染器
renderer, err := sdlrenderer.NewRenderer(window)
if err != nil {
panic(err)
}
defer renderer.Destroy()
// 初始化ImGui
context := imgui.CreateContext(nil)
defer context.Destroy()
io := imgui.CurrentIO()
// 初始化ImGui SDL2绑定
impl := sdlrenderer.New(renderer)
defer impl.Dispose()
impl.SetWindow(window)
// 主循环
running := true
for running {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
running = false
}
impl.ProcessEvent(event)
}
// 开始新帧
impl.NewFrame()
imgui.NewFrame()
// 创建GUI界面
imgui.Begin("Hello, world!")
imgui.Text("This is some useful text.")
if imgui.Button("Click me!") {
// 按钮点击处理
}
imgui.End()
// 渲染
imgui.Render()
impl.Render(imgui.RenderedDrawData())
renderer.Present()
sdl.Delay(16) // 约60FPS
}
}
常用组件使用
按钮和文本
imgui.Button("Click me")
imgui.Text("Simple text")
imgui.TextColored(imgui.Vec4{X: 1, Y: 0, Z: 0, W: 1}, "Red text")
输入框
var text string
imgui.InputText("Input", &text)
滑块和数值输入
var value float32 = 0.5
imgui.SliderFloat("Slider", &value, 0, 1)
imgui.InputFloat("Input float", &value)
复选框
var checked bool
imgui.Checkbox("Checkbox", &checked)
下拉菜单
var currentItem int32
items := []string{"Option 1", "Option 2", "Option 3"}
imgui.Combo("Combo", ¤tItem, items)
颜色选择器
var color [4]float32 = [4]float32{1, 0, 0, 1}
imgui.ColorEdit4("Color", &color)
布局控制
窗口
imgui.Begin("Window Title")
// 窗口内容
imgui.End()
子窗口
imgui.BeginChild("Child", imgui.Vec2{X: 200, Y: 100}, true)
// 子窗口内容
imgui.EndChild()
分组
imgui.BeginGroup()
// 分组内容
imgui.EndGroup()
表格
if imgui.BeginTable("table", 3, 0, imgui.Vec2{}, 0) {
imgui.TableSetupColumn("Column 1")
imgui.TableSetupColumn("Column 2")
imgui.TableSetupColumn("Column 3")
imgui.TableHeadersRow()
for i := 0; i < 5; i++ {
imgui.TableNextRow()
for j := 0; j < 3; j++ {
imgui.TableSetColumnIndex(j)
imgui.Text(fmt.Sprintf("Row %d, Col %d", i, j))
}
}
imgui.EndTable()
}
样式定制
你可以自定义ImGui的样式:
style := imgui.CurrentStyle()
style.SetColor(imgui.StyleColorText, imgui.Vec4{X: 1, Y: 1, Z: 1, W: 1}) // 白色文本
style.SetWindowRounding(0) // 无圆角窗口
高级功能
自定义字体
io := imgui.CurrentIO()
fontConfig := imgui.NewFontConfig()
defer fontConfig.Destroy()
fontConfig.SetSize(20) // 20px字体
// 加载TTF字体
font := io.Fonts().AddFontFromFileTTF("arial.ttf", 16, fontConfig)
绘图API
drawList := imgui.GetWindowDrawList()
pos := imgui.CursorScreenPos()
drawList.AddLine(
imgui.Vec2{X: pos.X, Y: pos.Y},
imgui.Vec2{X: pos.X + 100, Y: pos.Y + 100},
imgui.PackedColorFromVec4(imgui.Vec4{X: 1, Y: 0, Z: 0, W: 1}),
2.0, // 线宽
)
性能优化建议
- 避免在每帧创建临时字符串,尽量重用变量
- 对于不常变化的内容,使用
imgui.BeginChild()
和imgui.EndChild()
限制更新区域 - 对于复杂界面,考虑使用
imgui.SetNextWindowSizeConstraints()
限制窗口大小 - 使用
imgui.BeginDisabled()
和imgui.EndDisabled()
来禁用不需要交互的部分
总结
cimgui-go为Go开发者提供了使用Dear ImGui的便捷方式,可以创建高性能的GUI应用程序。它的即时模式设计使得UI开发变得直观简单,特别适合工具、编辑器等需要频繁更新的界面。
要了解更多细节,可以参考cimgui-go的GitHub仓库和Dear ImGui的官方文档。