golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用

Golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用

cimgui-go是一个为Golang生成的Dear ImGui包装器项目,它提供了多个默认的后端实现,支持macOS(arm64/x86)、Windows(x64)和多种Linux发行版。

项目状态

Go Report Card Build Status Linter Status GoDoc Mentioned in Awesome Go

模块概述

包名 描述
imgui, implot, imnodes Dear ImGui(及其插件)的实际绑定,用于显示小部件和其他UI内容
examples 展示如何使用cimgui-go的示例
cmd/codegen 生成Go绑定的代码生成器
backend 各种后端(glfw, sdl, ebiten等)的抽象层
backend/* 具体的后端实现
impl 负责imgui与后端交互的包
cwrappers Dear ImGui的C包装器
lib 预编译的静态库
thirdparty 第三方头文件如GLFW和SDL2
utils 一些实用函数

支持的后端

cimgui-go实现了几个ImGui后端,都放在backend/子包中:

  • GLFW (GLFW 3.3 + OpenGL)
  • SDL2 (SDL 2 + OpenGL)
  • Ebitengine (import "github.com/AllenDang/cimgui-go/backend/ebitenbackend")

重要提示:不同解决方案使用不同的C库可能会相互冲突。建议不要同时导入GLFW和SDL后端,这可能导致链接器崩溃。

示例代码

下面是一个使用GLFW后端的完整示例:

package main

import (
	"github.com/AllenDang/cimgui-go"
	"github.com/AllenDang/cimgui-go/backend/glfw"
)

func main() {
	// 初始化GLFW后端
	backend, err := glfw.NewBackend("Demo", 1024, 768)
	if err != nil {
		panic(err)
	}
	defer backend.Dispose()

	// 初始化ImGui上下文
	imgui.CreateContext(nil)
	defer imgui.DestroyContext(nil)

	// 设置ImGui IO
	io := imgui.CurrentIO()
	io.SetIniFilename("") // 禁用imgui.ini文件

	// 初始化ImGui GLFW绑定
	backend.SetAfterCreateContextHook(func() {
		glfw.InitGLFW()
	})
	backend.SetBeforeDestroyContextHook(func() {
		glfw.ShutdownGLFW()
	})

	// 主循环
	for backend.PollEvents() {
		// 开始新帧
		backend.NewFrame()
		imgui.NewFrame()

		// 在这里构建UI
		imgui.ShowDemoWindow(nil)

		// 渲染
		imgui.Render()
		backend.Render(imgui.RenderedDrawData())
	}
}

命名约定

  • 对于函数,'Im/ImGui/ig’前缀被去除
  • Get前缀也被移除(有一些例外)
  • 如果函数来自imgui_internal.h,则添加Internal前缀

指针和切片

在C中无法区分指针和切片,我们的代码默认使用指针,但你可以通过&(slice[0])轻松将切片转换为指针。

实用函数:

  • utils.SliceToPtr(slice []T) *T - 将切片转换为指针
  • utils.PtrToSlice(ptr *T, size int) []T - 将指针转换为给定大小的切片(使用时需小心size参数)

回调函数

目前Go(1.24)不支持通过CGO将匿名函数传递给C。我们有一个解决方案-预生成大量全局函数和一个池。请注意限制,可能会用完预生成的池并导致崩溃。

应用程序演示

App demo

贡献指南

所有类型的贡献都欢迎!但请注意:

警告:你绝不应该手动修改自动生成的文件!违反此规则的所有Pull Request都将无法通过自动检查并且不会被合并。

当前解决方案是:

  1. 使用cimgui的lua生成器生成函数和结构体定义为json
  2. 从定义生成适当的Go代码
  3. 使用来自imgui的后端实现
  4. 使用github workflow编译cimgui、glfw和其他C依赖项为静态库

要生成Go绑定,你需要:

  • 安装GNU make
  • 安装Go

然后只需运行make,或make XXX(其中XXX是你想要生成的包名,如make imguimake implot等)。


更多关于golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于Dear ImGui的GUI界面开发插件库cimgui-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用cimgui-go进行Golang GUI开发

cimgui-go是Golang绑定Dear ImGui的库,让你可以用Go语言创建轻量级、高效的图形用户界面。下面我将介绍如何使用cimgui-go进行GUI开发。

安装cimgui-go

首先需要安装cimgui-go:

go get github.com/inkyblackness/imgui-go/v4

基本使用示例

下面是一个简单的cimgui-go示例,创建一个带有按钮和文本的窗口:

package main

import (
	"github.com/inkyblackness/imgui-go/v4"
	"github.com/faiface/mainthread"
	"github.com/go-gl/glfw/v3.3/glfw"
)

func main() {
	mainthread.Run(run)
}

func run() {
	// 初始化GLFW
	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	// 创建窗口
	window, err := glfw.CreateWindow(1280, 720, "cimgui-go示例", nil, nil)
	if err != nil {
		panic(err)
	}
	defer window.Destroy()

	window.MakeContextCurrent()
	glfw.SwapInterval(1)

	// 创建ImGui上下文
	context := imgui.CreateContext(nil)
	defer context.Destroy()

	// 初始化ImGui GLFW绑定
	imguiGLFW := imgui.NewGLFW(window)
	defer imguiGLFW.Shutdown()

	// 初始化ImGui OpenGL绑定
	imguiOpenGL := imgui.NewOpenGL3()
	defer imguiOpenGL.Shutdown()

	// 主循环
	for !window.ShouldClose() {
		glfw.PollEvents()

		// 开始新帧
		imguiOpenGL.NewFrame()
		imguiGLFW.NewFrame()
		imgui.NewFrame()

		// 创建UI
		imguiDemo()

		// 渲染
		imgui.Render()
		imguiOpenGL.Render(imgui.RenderedDrawData())

		window.SwapBuffers()
	}
}

func imguiDemo() {
	// 创建一个窗口
	imgui.Begin("Hello, cimgui-go!")
	defer imgui.End()

	// 添加文本
	imgui.Text("这是一个简单的ImGui示例")

	// 添加按钮
	if imgui.Button("点击我") {
		// 按钮被点击时的处理
		println("按钮被点击!")
	}

	// 添加滑动条
	var value float32 = 0.5
	imgui.SliderFloat("滑动条", &value, 0, 1)
}

常用UI组件

按钮和文本

imgui.Text("这是一段文本")
if imgui.Button("按钮") {
    println("按钮被点击")
}

输入框

var text string
imgui.InputText("输入框", &text)

复选框

var checked bool
imgui.Checkbox("复选框", &checked)

单选按钮

var option int
imgui.RadioButton("选项1", &option, 0)
imgui.SameLine()
imgui.RadioButton("选项2", &option, 1)

下拉菜单

var currentItem int32
items := []string{"选项1", "选项2", "选项3"}
if imgui.BeginCombo("下拉菜单", items[currentItem]) {
    for i, item := range items {
        if imgui.Selectable(item) {
            currentItem = int32(i)
        }
    }
    imgui.EndCombo()
}

布局控制

水平布局

imgui.BeginGroup()
imgui.Button("按钮1")
imgui.SameLine()
imgui.Button("按钮2")
imgui.EndGroup()

子窗口

imgui.BeginChild("子窗口", imgui.Vec2{200, 100}, true)
imgui.Text("子窗口内容")
imgui.EndChild()

样式定制

你可以定制ImGui的样式:

style := imgui.CurrentStyle()
style.SetColor(imgui.StyleColorText, imgui.Vec4{1, 1, 0, 1}) // 黄色文本
style.ScaleAllSizes(1.5) // 放大所有UI元素

高级功能

绘制自定义图形

drawList := imgui.WindowDrawList()
pos := imgui.CursorScreenPos()
drawList.AddRect(
    pos,
    imgui.Vec2{X: pos.X + 100, Y: pos.Y + 100},
    imgui.PackedColor(1, 0, 0, 1), // 红色
)

使用字体

// 加载字体
io := imgui.CurrentIO()
font := io.Fonts().AddFontFromFileTTF("arial.ttf", 18)
if font == nil {
    font = io.Fonts().AddFontDefault()
}

// 使用字体
imgui.PushFont(font)
imgui.Text("使用自定义字体")
imgui.PopFont()

性能优化建议

  1. 尽量减少UI重建次数,只在必要时更新UI
  2. 使用imgui.BeginChild()分割复杂UI
  3. 避免在每帧中创建大量临时字符串
  4. 对于静态内容,考虑缓存渲染结果

总结

cimgui-go提供了Golang绑定Dear ImGui的能力,让你可以创建高效、跨平台的GUI应用程序。虽然API与C++版本略有不同,但核心概念和功能保持一致。通过组合各种UI组件和布局控制,你可以构建复杂的用户界面。

更多高级用法和示例可以参考cimgui-go的GitHub仓库和Dear ImGui的官方文档。

回到顶部