Go Gio 實(shí)戰(zhàn):煮蛋計(jì)時(shí)器的實(shí)現(xiàn) 03— 按鈕
上篇文章介紹了空窗口的實(shí)現(xiàn)。今天看看如何控制窗口,比如標(biāo)題、大小等。
01 目標(biāo)
GUI 程序,按鈕是少不了的,對按鈕點(diǎn)擊事件的響應(yīng),是必須掌握的知識點(diǎn)。通過本文的學(xué)習(xí),可以掌握 GUI 事件響應(yīng)的編程方法。
本節(jié)效果如下:

02 主要內(nèi)容
本節(jié)將介紹許多新組件,不過不會(huì)太深入細(xì)節(jié),而是專注于程序的整體結(jié)構(gòu)。雖然只是增加按鈕,但需要導(dǎo)入不少相關(guān)新包,因此需要花點(diǎn)時(shí)間了解下。之后會(huì)看看如何聯(lián)合 operations和widgets 來制作一個(gè)按鈕。
最后,我們談到了 Material Design[1],這是一個(gè)完善的用戶界面框架(Google 出品的),也可以在 Gio 中使用。
03 需要用的到包
本節(jié)會(huì)導(dǎo)入如下包:
import?(
??"gioui.org/app"
??"gioui.org/font/gofont"
??"gioui.org/io/system"
??"gioui.org/layout"
??"gioui.org/op"
??"gioui.org/unit"
??"gioui.org/widget"
??"gioui.org/widget/material"
)
對這些包做一個(gè)說明,其中 app 和 unit 之前有介紹過,因此介紹其他的包。
font/gofont[2] - Go 自己有一套高質(zhì)量的 True Type 字體,這是對其進(jìn)行封裝,導(dǎo)出給 gioui.org/text 包使用。關(guān)于官方的這套字體,可以閱讀 Go 官方的博文:https://go.dev/blog/go-fonts。
io/system[3] - 提供從窗口發(fā)送的高級事件。最重要的是
system.FrameEvent。它實(shí)際上是執(zhí)行以下兩項(xiàng)操作之一的操作列表:詳細(xì)說明如何處理輸入并描述要顯示的內(nèi)容。layout[4] - 定義布局中的有用可變部分,例如尺寸、約束和方向。此外,它還包括稱為 Flexbox[5] 的布局概念。它被廣泛用于 Web 和用戶界面開發(fā),詳情可以參考 Mozilla 上的介紹[6]。
op[7] - Operations 或 ops 是 Gio 的核心。它們用于更新用戶界面。有一些操作用于繪制、處理輸入、更改窗口屬性、縮放、旋轉(zhuǎn)等。有趣的是還有宏[8],可以記錄稍后要執(zhí)行的操作。總之,這意味著操作列表是一個(gè)可變堆棧,你可以在其中控制流程。
widget[9] - 小部件提供 UI 組件的底層功能,例如狀態(tài)跟蹤和事件處理。鼠標(biāo)是否懸停在按鈕上?是否被點(diǎn)擊過,如果有,點(diǎn)擊了多少次?
widget/material[10] - 雖然
widget提供功能,但widget/material定義了一個(gè)主題。請注意,該界面實(shí)際上分為兩部分:這是為了提高小部件的可重用性和靈活性。我們稍后會(huì)用到它。
默認(rèn)看起來不錯(cuò),也是我們將使用的,但通過設(shè)置顏色、文本大小字體屬性等屬性也很容易調(diào)整。
注意:Gio 在名為 gio-x[11] 的專用存儲(chǔ)庫中擴(kuò)展了基本功能,其中正在開發(fā)更多材質(zhì)組件[12],包括導(dǎo)航欄和工具提示。 具有狀態(tài)的實(shí)際小部件 小部件的繪制,完全無狀態(tài)
04 功能實(shí)現(xiàn)
看看本文開頭提到的按鈕功能如何實(shí)現(xiàn),代碼如下:
func?main()?{
?go?func()?{
??//?創(chuàng)建一個(gè)新窗口
??w?:=?app.NewWindow(
???app.Title("煮蛋計(jì)時(shí)器"),
???app.Size(unit.Dp(400),?unit.Dp(600)),
??)
??//?ops?表示?UI?上的操作
??var?ops?op.Ops
??//?startButton?時(shí)候一個(gè)可點(diǎn)擊的小部件
??var?startButton?widget.Clickable
??//?th?定義?material?design(材料設(shè)計(jì))的風(fēng)格
??th?:=?material.NewTheme(gofont.Collection())
??//?循環(huán)監(jiān)聽窗口上的事件
??for?e?:=?range?w.Events()?{
???//?監(jiān)聽事件的類型
???switch?e?:=?e.(type)?{
???//?當(dāng)應(yīng)用程序需要重新渲染是發(fā)送該事件
???case?system.FrameEvent:
????gtx?:=?layout.NewContext(&ops,?e)
????btn?:=?material.Button(th,?&startButton,?"Start")
????btn.Layout(gtx)
????e.Frame(gtx.Ops)
???}
??}
?}()
?app.Main()
}
05 代碼詳解
主要關(guān)注這次新增的內(nèi)容。
1)設(shè)置了三個(gè)新變量
ops從用戶界面定義操作,具體的作用說明,介紹 op 包時(shí)講解了。startButton是我們的按鈕,一個(gè)可點(diǎn)擊的小部件。th是材料設(shè)計(jì)主題,設(shè)置字體為 gofonts。
2)事件循環(huán)代碼:
for?e:=?range?w.Events()
是重點(diǎn):
w.Events()方法的返回值類型是:<-chan event.Event,為我們提供了傳遞事件的 channel。我們只是循環(huán)監(jiān)聽。event.Event是一個(gè)接口。因此,在循環(huán)里面,我們需要進(jìn)行斷言,對不同的事件做不同的響應(yīng)。在這個(gè)例子中,我們只對事件 system.FrameEvent進(jìn)行處理。具體處理邏輯:請注意,我們?nèi)绾屋p松獲得所有鼠標(biāo)懸停和點(diǎn)擊動(dòng)畫。它們都是主題(theme)的一部分,很贊。 我們定義一個(gè)新的圖形上下文即 gtx。它接收指向ops的指針以及事件system.FrameEvent。btn是實(shí)際的按鈕,material.Button接收主題th和指向startButton小部件的指針。我們還定義了顯示的文本(注意,文本是純粹顯示在按鈕上的,而不是按鈕這個(gè)有狀態(tài)小部件的一部分。)btn.Layout(gtx)表示按鈕btn要求在上下文gtx中顯示自己。這是關(guān)鍵。布局不布局按鈕,按鈕自己布局。這非常方便,例如嘗試調(diào)整窗口大小。無論畫布的大小或形狀如何,按鈕都會(huì)重新調(diào)整自己。最終,我們實(shí)際將操作 ops從上下文gtx發(fā)送到 FrameEvente。
最后,記得實(shí)際動(dòng)手運(yùn)行看看。我們并沒有設(shè)置實(shí)際的按鈕點(diǎn)擊樣式,Gio 自動(dòng)幫我們做了。
06 小結(jié)
本節(jié)雖然只是實(shí)現(xiàn)一個(gè)按鈕,但涉及到的知識點(diǎn)不少,關(guān)鍵代碼就幾行,但需要花些時(shí)間了解下相關(guān) API 的用法,掌握使用 Gio 實(shí)現(xiàn) GUI 的關(guān)鍵步驟和思路。
參考:https://jonegil.github.io/gui-with-gio/egg_timer/03_button.html。
參考資料
Material Design: https://material.io/
[2]font/gofont: https://pkg.go.dev/gioui.org/font/gofont
[3]io/system: https://pkg.go.dev/gioui.org/io/system
[4]layout: https://pkg.go.dev/gioui.org/layout
[5]Flexbox: https://pkg.go.dev/gioui.org/layout#Flex
[6]Mozilla 上的介紹: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox
[7]op: https://pkg.go.dev/gioui.org/op
[8]宏: https://pkg.go.dev/gioui.org/op#MacroOp
[9]widget: https://pkg.go.dev/gioui.org/widget
[10]widget/material: https://pkg.go.dev/gioui.org/widget/material
[11]gio-x: https://pkg.go.dev/gioui.org/x
[12]更多材質(zhì)組件: https://pkg.go.dev/gioui.org/x/component
我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語言并創(chuàng)建了 Go 語言中文網(wǎng)!著有《Go語言編程之旅》、開源圖書《Go語言標(biāo)準(zhǔn)庫》等。
堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio
