百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

GoUI:一个非常简单的 GUI 框架(go流行框架)

ccwgpt 2024-10-02 12:04 26 浏览 0 评论

最近,我一直想开发一些桌面(主要是 Windows,但也可以考虑 MacOS 或 Linux)应用程序。虽然 Go 不是开发 UI 应用程序时首选语言,但是该语言的简单性和健壮性仍然使它成为我的首选语言。是的,这是我的锤子(hammer)... 但这是一个该死的漂亮锤子。

以前,我曾将 Ebiten 图形库用于 Go,以便与孩子们一起编写一些游戏。但是,对于一般的“应用程序”开发(即需要“小部件 widgets”,例如按钮,菜单等),Ebiten 并非真的适合。因此,我一直在寻找可以使用的 Go UI 库。然而大多数都使用 cgo,但我真的希望我的应用程序是纯 Go。这纯粹是个人喜好,我不知道使用 cgo 而不是纯 Go 会有什么影响。如果我要使用 cgo,我认为首选的 UI 库肯定是 Fyne[1]。Fyne 看起来是一个非常全面的框架,如果您不介意 cgo,我绝对会建议你看看看 Fyne。

还有其他一些库,但没有吸引我。他们说你永远不应该编写自己的安全性代码,并且我也相信你不应该编写自己的 UI 库。但是我忽略了这个建议...

因此,我写了一个 GoUI[2] !!

这纯粹是那些“抓痒”的项目之一。虽然现在还很早,但 UI 库的基本知识(由 Ebiten 进行实际渲染)正在慢慢融合。在详细介绍下面细节之前,我想先说明一下,我认为程序在 CLI 达到了顶峰。其次,我不是 UI 编程人员……写这些是我个人的兴趣。

GoUI 的基本思想是两种类型的图形元素。一个是可以包含其他面板或小部件的面板(Panel)。另一个是小部件,它是基本的 UI 元素(按钮,文本输入等)。我们目前使用的面板类型有 HPanel(水平添加)和 VPanel(我让你猜)。从技术上讲,我们确实有其他面板,例如工具栏,但这实际上只是 HPanel,需要一点点定制工作。总体而言,如果我可以结合其他现有面板/小工具来构造一些“新”东西,那么我会做的。如果我需要优化或与已有产品脱节,那么我将做一些全新的事情。

我们目前拥有的小部件是:

  • ImageButton:(由应用程序提供的单击/未单击的图像)。
  • TextButton:基本的彩色矩形,其中包含您想要的任何文本。
  • Checkbox:与 TextButton 相同,但是旁边有一个小方框,可以打对勾。
  • EmptySpace:完全由我控制。用于强制其他小部件之间的空间。一旦添加适当的填充,该填充可能会消失。
  • Label:文本标签,不能输入。
  • Text Input:文本输入框。
  • RadioButtonGroup:这是一个面板,其中包含 vpanel 或 hpanel(取决于标志),然后其中包含许多复选框。复选框将图像(带有刻度)替换为常规的单选按钮。这是重新使用现有窗口小部件的好例子。如果事实证明我需要对复选框进行足够的修改以使其不适合用作单选按钮,那么我将不得不放入一个真正的单选按钮。但是目前,它运行良好。

我还没有完成菜单,模态窗口等,但是正如我所说的……这还是早期。

现在,让我们尝试一个超级简单的 Demo。

package main
 
import (
    "github.com/hajimehoshi/ebiten"
    "github.com/kpfaulkner/goui/pkg"
    "github.com/kpfaulkner/goui/pkg/widgets"
    log "github.com/sirupsen/logrus"
    "image/color"
)
 
type MyApp struct {
    window pkg.Window
}
 
func NewMyApp() *MyApp {
    a := MyApp{}
    a.window = pkg.NewWindow(800, 600, "test app", false, false)
    return &a
}
 
func (m *MyApp) SetupUI() error {
    vPanel := widgets.NewVPanel("main vpanel", &color.RGBA{0, 0, 0, 0xff})
    m.window.AddPanel(vPanel)
    button1 := widgets.NewTextButton("text button 1", "my button1", true, 0, 0, nil, nil, nil, nil)
    vPanel.AddWidget(button1)
    return nil
}
 
func (m *MyApp) Run() error {
    m.SetupUI()
    ebiten.SetRunnableInBackground(true)
    ebiten.SetWindowResizable(true)
    m.window.MainLoop()
    return nil
}
 
func main() {
    log.SetLevel(log.DebugLevel)
    app := NewMyApp()
    app.Run()
}

让我们解释一下以上代码。

首先,该程序的核心仍然是直接调用 Ebiten。这些尚未封装。因此,你将在 main 和 Run 函数中看到,我们基本上已经制作了 MyApp 结构的实例,然后调用 SetupUI,设置一些 Ebiten 标志,然后调用 MainLoop。

NewMyApp 函数调用 pkg.NewWindow 函数。这是应用程序的主窗口。一旦添加了模态/其他窗口,这可能会更改,但是就目前而言,这将创建给定大小的主 UI 窗口。

SetupUI 是你需要注意的地方。我们要做的第一件事是创建一个 VPanel。请记住,VPanel 把小部件垂直堆叠放置。我们将 vPanel 添加到主窗口。实际上(当前),我们应该只在主窗口中添加 1 个面板,其他所有内容都应放入该面板中。因此,在这种情况下,我们创建 button1(新的 TextButton)并将其添加到 vPanel。

花点时间来学习理解一下上面的 UI 技能。

下面,让我们做一些更有趣的事情。假设我们要在按下按钮时做出响应。创建 TextButton 的行是:

button1 := widgets.NewTextButton("text button 1", "my button1", true, 0, 0, nil, nil, nil, nil)

所有细节就不描述了,但是最后一个参数是带有 func (event IEvent) error签名的事件处理程序。因此,如果我们创建一个带有该签名的方法,并将其作为最后一个参数传递给 NewTextButton。

func (m *MyApp) ButtonAction1(event events.IEvent) error {
    log.Debugf("My button1 action 1!!!")
    return nil
}

然后我们将按钮创建修改为

button1 := widgets.NewTextButton("text button 1", "my button1", true, 0, 0, nil, nil, nil, m.ButtonAction1)

现在,当单击按钮时,将调用 ButtonAction1 函数,我们可以触发所需的任何功能。

是不是很简单。

现在,如果我想要在按钮旁边放点东西该怎么办?我们在这里要做的是创建一个 HPanel,并将其首先放入 VPanel。然后,将按钮添加到 HPanel。如果这样做,我们最终将得到如下代码:

func (m *MyApp) SetupUI() error {
 
    vPanel := widgets.NewVPanel("main vpanel", &color.RGBA{0, 0, 0, 0xff})
    m.window.AddPanel(vPanel)
 
    hPanel := widgets.NewHPanel("hpanel1", &color.RGBA{0, 100, 0, 255})
    vPanel.AddWidget(hPanel)
 
    button1 := widgets.NewTextButton("text button 1", "my button1", true, 0, 0, nil, nil, nil, m.ButtonAction1)
    hPanel.AddWidget(button1)
 
    return nil
}

从视觉上看,什么都不会改变。我们仍然只显示 1 个小部件。

现在,如果我们在同一 HPanel 中添加一个复选框怎么办?

func (m *MyApp) SetupUI() error {
 
    vPanel := widgets.NewVPanel("main vpanel", &color.RGBA{0, 0, 0, 0xff})
    m.window.AddPanel(vPanel)
 
    hPanel := widgets.NewHPanel("hpanel1", &color.RGBA{0, 100, 0, 255})
    button1 := widgets.NewTextButton("text button 1", "my button1", true, 0, 0, nil, nil, nil, m.ButtonAction1)
    hPanel.AddWidget(button1)
 
    cb1 := widgets.NewCheckBox("my checkbox1", "check me please", "", "", nil)
    hPanel.AddWidget(cb1)
 
    vPanel.AddWidget(hPanel)
    return nil
}

因此,与之前完全相同,但只有这额外的两条:创建复选框,然后添加到 hPanel。

现在 UI 看起来是这样:

现在不担心这里的间距了。

现在让我们在 TextButton 下面添加一个 ImageButton。这意味着我们将向 vPanel 添加第二项(第一项是 hPanel)

imageButton := widgets.NewImageButton("ib1", "images/pressedbutton.png", "images/nonpressedbutton.png",nil )
vPanel.AddWidget(imageButton)

这是效果如下:

这时,我们有了 2 张图片(屏幕截图中只显示了一张)。按下按钮时一个,不按下时一个(只更改了阴影)。懂了吧。

好了,介绍就这么多。虽然该 UI 库还不完善,但 GUI 的基本功能已经可以实现了。再次放上该库的地址:https://github.com/kpfaulkner/goui。

作者:kpfaulkner[3]

日期:2020 年 8 月 17 日

原文链接:https://kpfaulkner.wordpress.com/2020/08/17/goui-a-very-simple-ui-framework/

译者:polaris

参考资料

[1]

Fyne: https://fyne.io/

[2]

GoUI: https://github.com/kpfaulkner/goui

[3]

kpfaulkner: https://kpfaulkner.wordpress.com/author/kpfaulkner/


相关推荐

Dubbo最全详解(万字图文总结)

大家好,我是mikechen。Dubbo是非常重要的分布式中间件,也是微服务的核心框架,而且大厂也特别喜欢考察Dubbo,下面我就全面来详解Dubbo@mikechen本篇已收于mikechen原创超...

探秘Dubbo:RPC框架的奇妙世界

探秘Dubbo:RPC框架的奇妙世界大家好啊!今天我要带大家走进一个神奇的编程领域——分布式服务调用。说起分布式系统,很多程序员都头疼不已。但今天咱们不谈那些让人抓狂的网络延迟、负载均衡等问题,而是聚...

Dubbo分布式服务框架:像调教宠物一样驾驭它

Dubbo分布式服务框架:像调教宠物一样驾驭它大家好呀,今天我们来聊聊Dubbo这个分布式服务框架,它就像一只温顺的小猫咪,但有时候也会调皮捣蛋,所以得好好调教一番。别担心,我会用最轻松的方式来帮你搞...

深入浅出:Dubbo框架源码分析

深入浅出:Dubbo框架源码分析Dubbo是一款由阿里巴巴开源的高性能分布式服务框架,广泛应用于微服务架构中。它为开发者提供了强大的RPC调用能力,使得分布式系统中的服务间通信变得简单高效。本文...

Dubbo分布式服务框架:从零开始的实战之旅

Dubbo分布式服务框架:从零开始的实战之旅Dubbo作为一个高性能的JavaRPC框架,在微服务架构中扮演着重要角色。它能帮助开发者轻松构建分布式系统,实现服务间的高效通信。今天,我们就来一起探索...

Dubbo分布式服务框架的工作原理:从入门到精通

Dubbo分布式服务框架的工作原理:从入门到精通Dubbo是一个高性能的Java分布式服务框架,由阿里巴巴开源。它致力于提供透明化的远程方法调用(RPC),使得开发者能够像调用本地服务一样调用远程服务...

框架的本质分析——Dubbo

诞生的背景什么背景下诞生了该技术?不论是哪个框架,不会平白无故诞生,不会平白无故的被人所追捧,了解其背景,追根溯源。随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架...

2023编导艺考「热点话题」评述框架示例(七个2022热点)

2022冬奥会开幕式(1)“旧”文化符号的“新”应用(2)“全媒体”时代的“小人物”(3)“简约”的形式表达“丰富”的内核(4)“新”叙事结构打破“旧”国家形象(5)数字媒介增强受众“在场感”短视频“...

84页思考的框架,思维模型的全明星集合,9种经典思维模型

分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!84页思考的框架如何拿到分享的源文件:请您关注、转发,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...

DUSt3R-从任意图像集合中重建3D场景的框架

DUSt3R是什么DUSt3R(DenseandUnconstrainedStereo3DReconstruction,密集无约束立体三维重建)是由来自芬兰阿尔托大学和Naver欧洲实验室的...

高考数学:一张思维导图掌握集合知识点,真题解析巩固知识

一、思维导图二、疑难透析三、题型示例1、已知集合A={1,3},B={x丨mx-3=0},且A∪B=A,则m的取值是()。【解析】分类讨论思想∵AUB=A∴BA(1)当m=0时,B=,符合条件;...

java集合框架03——ArrayList和源码分析

上一章学习了Collection的架构,并阅读了部分源码,这一章开始,我们将对Collection的具体实现进行详细学习。首先学习List。而ArrayList又是List中最为常用的,因此本章先学习...

Java Collections 工具类集合框架中常用算法解析

在软件开发中,算法是非常重要的一部分,它们可以提供高效的数据处理和操作。在Java集合框架中,有几个常用的算法,包括排序算法、二分查找算法、洗牌算法和旋转算法。本文将对这些算法进行详细解析,并写了一些...

1.6、Java 异常处理机制与集合框架(List、Set、Map等)

在Java编程中,异常处理机制和集合框架是两个非常重要的概念。前者帮助开发者处理程序运行时可能遇到的错误,确保程序能够稳定运行;后者则提供了一种有效的方式来管理和操作数据集合。本文将分别介绍Java中...

Java集合框架性能优化秘籍

Java集合框架性能优化秘籍在Java的世界里,集合框架就像一座巨大的宝库,存储着我们程序的各种数据。然而,随着数据量的增大,如何让这座宝库更高效地运作,就成了我们必须掌握的艺术。今天,我们就来聊聊J...

取消回复欢迎 发表评论: