Go Gio 实战:煮蛋计时器的实现 01 — 空窗口

Go语言精选

共 2220字,需浏览 5分钟

 ·

2021-11-04 17:30

接下来我们将一步步实通过 gio 实现一个煮蛋计时器。

这是完全从头开始实现的,使用 Gio 这个 Go GUI 库实现的独立 Go 应用程序,会解释每一个步骤。

实现的最终效果如下:

本系列大纲:

  • 第 1 章 - 空窗口
  • 第 2 章 - 标题和大小
  • 第 3 章 - 按钮
  • 第 4 章 - 低按钮(Low Button)
  • 第 5 章 - 重构
  • 第 6 章 - 带边距的按钮
  • 第 7 章 - 进度条
  • 第 8 章 - 画圆
  • 第 9 章 画鸡蛋
  • 第 10 章 - 输入沸腾时间

先看如何实现一个空窗口。

01 目标

本节的目的是创建一个空白画布,我们稍后可以在其上进行绘制。

An empty window

02 主要内容

本节代码主要做三件事:

  • 导入 Gio
  • 创建并调用 goroutine:
    • 创建一个新窗口:w
    • 启动一个无限循环,等待窗口中的事件,具体事件后续实现

接下来看看具体的代码。

03 代码

package main

import (
 "gioui.org/app"
)

func main() {
 go func() {
  // 创建一个新窗口(Window)
  w := app.NewWindow()

  // 监听窗口的事件
  for range w.Events() {
  }
 }()
 app.Main()
}

04 代码详解

代码看起来很简单。不过,还是花点时间看看发生了什么,毕竟 GUI 编程大家接触的少。

1)我们导入了 gioui.org/app,它干什么用的?

我们需要查看文档:https://pkg.go.dev/gioui.org/app:

包 app 为运行图形用户界面的操作系统功能提供了一个独立于平台的界面。

这是很棒的特性。Gio 为我们处理所有与平台相关的事情,这和 Go 一样,是跨平台的。

这可能比你意识到的要更重要。因为,即使你今天的应用程序是单平台的,但指不定哪天想迁移到其他平台。

上篇文章简单介绍了,Gio 对各个平台都有支持,包括移动端,甚至 tvOS。

2)goroutine 中的事件循环

  • 事件循环的代码是:for range w.Events(),它循环监听窗口中的事件。现在我们只是监听,并没有对事件做任何处理。后续章节会实现。

    app.Main[1] 我们了解到:

    因为 Main 在某些平台上也是阻塞的,所以 Window 的事件循环必须在 goroutine 中运行。

    有 Go 经验的同学应该理解这块内容。因为如果 app.Main 不堵塞,最后 main 函数就返回,程序退出了。

  • 一个没有名字的 goroutine,即匿名函数,被创建并运行事件循环。由于它在 goroutine 中,它将与程序的其余部分同时运行。

    go func {
      // ...
    }()

    这是 Go 语言常见的写法。

3)最后上文提到的调用 app.Main() 启动程序,app.Main 的文档提到:

Main 函数必须从程序的 main 函数中调用,以便将主线程的控制权移交给需要它的操作系统。Main 的具体实现,不同系统不一样。

比如 Unix、Windows 等系统,直接调用 select {},感兴趣的可以查看 gio 的源码。

不过,上面的简单代码,在 Mac 下运行不正常,会 panic:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x40f7f85]

可以先忽略。如果就想看看,可以用下面代码:

package main

import (
 "gioui.org/app"
 "gioui.org/io/system"
 "gioui.org/layout"
 "gioui.org/op"
)

func main() {
 go func() {
  w := app.NewWindow()

  var ops op.Ops
  for e := range w.Events() {
   switch e := e.(type) {
   case system.FrameEvent:
    gtx := layout.NewContext(&ops, e)
    e.Frame(gtx.Ops)
   }
  }
 }()
 app.Main()
}

05 小结

通过 gio 创建 GUI 应用程序,和普通服务端应用程序类似:

  • 一个循环,处理各种事件
  • 一个堵塞,好比 select{} 或 HTTP 服务中的 http.ListenAndServe

赶紧动手试试吧!

参考资料

[1]

app.Main: https://pkg.go.dev/gioui.org/app#hdr-Main




推荐阅读


福利

我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。


浏览 291
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报