ZetCode

使用 giu 在 Go 中创建 UI

最后修改于 2024 年 4 月 30 日

在本文中,我们将展示如何使用跨平台的 giu 库在 Go 中创建 UI。

giu 是一个基于 Dear ImGui 的快速跨平台 GUI 框架,适用于 Go。Dear ImGui 是一个 C++ 的无膨胀图形用户界面库。

Dear ImGui 使用即时模式 GUI 范式来定义界面。与传统的工具包(如 Qt、Gtk 或 Swing)不同,在传统工具包中,我们创建单独的 UI 对象并管理它们的 state,而在即时模式中,我们直接告诉 GUI 库每一帧要绘制什么。

即时模式 GUI 常用于游戏开发。

giu 是 Dear ImGui C 接口的 Go 封装。它使用方便的构建器模式来构建小部件。

标签小部件

标签是一个显示文本的小部件。

main.go
package main

import (
    g "github.com/AllenDang/giu"
)

func loop() {

    g.SingleWindow().Layout(
        g.Label("An old falcon in the sky"),
    )
}

func main() {
    wnd := g.NewMasterWindow("Application", 400, 200,
        g.MasterWindowFlagsFloating)
    wnd.Run(loop)
}

在示例中,我们创建了一个显示一些文本的窗口。

import (
    g "github.com/AllenDang/giu"
)

我们导入库并给它起一个 `g` 的别名。

func loop() {

    g.SingleWindow().Layout(
        g.Label("An old falcon in the sky"),
    )
}

每一帧都会调用 `loop` 函数。在该函数中,我们创建应用程序的 UI。在我们的例子中,我们在窗口中创建了一个单一窗口和一个标签。

func main() {
    wnd := g.NewMasterWindow("Application", 400, 200,
        g.MasterWindowFlagsFloating)
    wnd.Run(loop)
}

在 `main` 函数中,我们创建了主窗口。`g.NewMasterWindow` 函数接受应用程序标题、窗口宽度和高度以及窗口标志作为参数。`Run` 函数运行主循环。在每一帧中,`loop` 函数用于构建 UI。`Run` 应在设置主窗口后,在 `main` 函数的末尾调用。

快捷键

键盘快捷键是在键盘上按下的组合键,用于执行操作。它们是通过 `RegisterKeyboardShortcuts` 创建的。

main.go
package main

import (
    "os"

    g "github.com/AllenDang/giu"
)

func loop() {

    g.SingleWindow().Layout(
        g.Label("Ctrl + Q to exit"),
    )
}

func main() {
    wnd := g.NewMasterWindow("Window", 400, 200, g.MasterWindowFlagsFloating).RegisterKeyboardShortcuts(
        g.WindowShortcut{
            Key:      g.KeyQ,
            Modifier: g.ModControl,
            Callback: func() { os.Exit(0) }},
    )
    wnd.Run(loop)
}

在示例中,我们定义了 `Ctrl+Q` 快捷键。它会终止应用程序。

wnd := g.NewMasterWindow("Window", 400, 200, g.MasterWindowFlagsFloating).RegisterKeyboardShortcuts(
    g.WindowShortcut{
        Key:      g.KeyQ,
        Modifier: g.ModControl,
        Callback: func() { os.Exit(0) }},
)

`RegisterKeyboardShortcuts` 在主窗口上调用。在 `g.WindowShortcut` 结构中,我们定义了按键、修饰键和回调。对于我们的快捷键,我们调用 `os.Exit` 函数来终止应用程序。

按钮小部件

按钮是一个基本的小部件,按下时会执行一个操作。

main.go
package main

import (
    "fmt"

    g "github.com/AllenDang/giu"
)

func loop() {
    g.SingleWindow().Layout(
        g.Button("Click").Size(80, 30).OnClick(func() {
            fmt.Println("button clicked")
        }),
    )
}

func main() {
    wnd := g.NewMasterWindow("Button", 400, 200, 0)
    wnd.Run(loop)
}

在示例中,按钮按下后会在控制台中写入一条消息。

g.SingleWindow().Layout(
    g.Button("Click").Size(80, 30).OnClick(func() {
        fmt.Println("button clicked")
    }),
)

按钮是通过 `g.Button` 创建的。`Size` 用于调整小部件大小。`OnClick` 函数定义了按钮单击事件的回调。

复选框小部件

复选框小部件是在用户界面中用于做出二元选择的图形元素。它是一个可以被选中或取消选中的小方框。

main.go
package main

import (
    g "github.com/AllenDang/giu"
)

var cbSelected bool = true

func loop() {

    g.SingleWindow().Layout(
        g.Checkbox("Show Title", &cbSelected).OnChange(
            func() {
                if cbSelected {
                    g.Context.GetPlatform().SetTitle("CheckBox")
                } else {
                    g.Context.GetPlatform().SetTitle("")
                }
            }),
    )
}

func main() {
    wnd := g.NewMasterWindow("Checkbox", 400, 200,
        g.MasterWindowFlagsFloating)
    wnd.Run(loop)
}

在示例中,复选框小部件在被选中时会显示一个窗口标题。

var cbSelected bool = true

这是存储小部件状态的布尔变量。

g.Checkbox("Show Title", &cbSelected).OnChange(
    func() {
        if cbSelected {
            g.Context.GetPlatform().SetTitle("CheckBox")
        } else {
            g.Context.GetPlatform().SetTitle("")
        }
    }),

复选框是通过 `g.Checkbox` 函数创建的。它接受标签和关联的状态变量作为参数。当复选框被选中或取消选中时,会调用 `OnChange` 函数。我们通过 `g.Context.GetPlatform().SetTitle()` 函数来更改窗口标题。

画布小部件

画布小部件用于绘制我们自定义的形状。

main.go
package main

import (
    "image"
    "image/color"

    g "github.com/AllenDang/giu"
)

func loop() {
    g.SingleWindow().Layout(
        g.Custom(func() {

            canvas := g.GetCanvas()
            col := color.RGBA{0, 140, 140, 255}

            canvas.AddLine(image.Pt(25, 25), image.Pt(100, 100), col, 1)
            canvas.AddRect(image.Pt(160, 25), image.Pt(260, 115),
                col, 5, g.DrawFlagsRoundCornersAll, 1)
            canvas.AddRectFilled(image.Pt(330, 25),
                image.Pt(430, 115), col, 5, 0)

            canvas.AddCircleFilled(image.Pt(150, 250), 60, col)
            canvas.AddTriangleFilled(image.Pt(330, 300),
                image.Pt(450, 200), image.Pt(500, 300), col)
        }),
    )
}

func main() {
    wnd := g.NewMasterWindow("Canvas", 450, 300,
        g.MasterWindowFlagsNotResizable)
    wnd.Run(loop)
}

在示例中,我们创建了一个画布小部件并绘制了一条线、两个矩形、一个圆和一个三角形。

g.Custom(func() {

画布放置在一个自定义小部件中。

canvas := g.GetCanvas()

我们使用 `g.GetCanvas` 获取当前窗口的画布。

col := color.RGBA{0, 140, 140, 255}

我们定义了一个颜色值。

canvas.AddLine(image.Pt(25, 25), image.Pt(100, 100), col, 1)

`AddLine` 函数在画布上绘制一条线。前两个参数是线的起点和终点。第三个参数是线的颜色。最后一个参数是线的粗细。

来源

giu Github 页面

在本文中,我们使用了 Go 中的 giu UI 库。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程