什么是fyne
fyne是为go语言开发跨平台的图形化应用程序出的一个工具包,通过fyne可以用go语言开发出兼容Mac OS、Linux、Windows、Android、IOS的应用程序。这篇文章只是一个简单的入门教程,如果想看详细的介绍,可以关注fyne的官网
创建go工程
1
2
|
cfp@cfp:~/program/go/fyne_sample$ go mod init fyne_sample
go: creating new go.mod: module fyne_sample
|
1
|
cfp@cfp:~/program/go/fyne_sample$ go get fyne.io/fyne/v2
|
1
|
cfp@cfp:~/program/go/fyne_sample$ go mod tidy
|
Hello World
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package main
import (
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.New()
w := a.NewWindow("Hello World!")
w.SetContent(widget.NewLabel("Hello World!"))
w.ShowAndRun()
}
|
应用和RunLoop
RunLoop就是程序在循环过程中处理各种事件,比如说触摸事件、UI刷新事件、定时器事件、Selector事件,从而保持程序的持续运行。
更新控件内容
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
a := app.New()
w := a.NewWindow("Hello World!")
clock := widget.NewLabel("")
w.SetContent(clock)
formatted := time.Now().Format("Time: 03:04:05")
clock.SetText(formatted)
w.ShowAndRun()
}
|
后台运行
如果你做过app开发,都直到如果你的程序有耗时任务时,需要将其放到后台执行,或者一个单独的线程去执行,不能直接在UI线程中执行,否则会阻塞UI线程,出现卡顿的情况。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func updateTime(clock *widget.Label) {
formatted := time.Now().Format("Time: 03:04:05")
clock.SetText(formatted)
}
func main() {
a := app.New()
w := a.NewWindow("Hello World!")
clock := widget.NewLabel("")
w.SetContent(clock)
go func() {
for range time.Tick(time.Second) {
updateTime(clock)
}
}()
w.ShowAndRun()
}
|
显示两个窗口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
func main() {
a := app.New()
w := a.NewWindow("Hello World!")
w.Resize(fyne.NewSize(500, 500))
w.SetContent(widget.NewLabel("Hello World!"))
w.Show()
w2 := a.NewWindow("Clock")
w2.Resize(fyne.NewSize(500, 500))
clock := widget.NewLabel("")
w2.SetContent(clock)
go func() {
for range time.Tick(time.Second) {
updateTime(clock)
}
}()
w2.Show()
a.Run()
}
|
通过一个窗口打开另外一个窗口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
func main() {
a := app.New()
w := a.NewWindow("Hello World!")
w.Resize(fyne.NewSize(500, 500))
w.SetContent(widget.NewLabel("Hello World!"))
w.Show()
w2 := a.NewWindow("Clock")
w2.Resize(fyne.NewSize(500, 500))
clock := widget.NewLabel("")
w2.SetContent(clock)
go func() {
for range time.Tick(time.Second) {
updateTime(clock)
}
}()
w2.Show()
w2.SetContent(widget.NewButton("Open new", func() {
w3 := a.NewWindow("window 3")
w3.SetContent(widget.NewLabel("window 3"))
w3.Resize(fyne.NewSize(500, 500))
w3.Show()
}))
a.Run()
}
|
打包
打包就是根据不同的平台,生产对应的可执行文件。
首先要安装fyne
1
|
go install fyne.io/fyne/v2/cmd/fyne
|
然后在工程目录执行
1
|
fyne package -os linux -icon logo.png
|
这样就会生产一个打包文件 fyne_sample.tar.xz
解压之后执行make
就可以进行安装了。
Canvas和CanvasObject
填充颜色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Canvas")
myCanvas := myWindow.Canvas()
blue := color.NRGBA{R: 0, G: 0, B: 180, A: 255}
rect := canvas.NewRectangle(blue)
myCanvas.SetContent(rect)
go func() {
time.Sleep(time.Second)
green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
rect.FillColor = green
rect.Refresh()
}()
myWindow.Resize(fyne.NewSize(500, 500))
myWindow.ShowAndRun()
}
|
文字和圆形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Canvas")
myCanvas := myWindow.Canvas()
blue := color.NRGBA{R: 0, G: 0, B: 180, A: 255}
rect := canvas.NewRectangle(blue)
myCanvas.SetContent(rect)
go func() {
time.Sleep(time.Second)
green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
rect.FillColor = green
rect.Refresh()
}()
setContentText(myCanvas)
setContentToCircle(myCanvas)
myWindow.Resize(fyne.NewSize(500, 500))
myWindow.ShowAndRun()
}
func setContentText(c fyne.Canvas) {
green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
text := canvas.NewText("Text", green)
text.TextStyle.Bold = true
c.SetContent(text)
}
func setContentToCircle(c fyne.Canvas) {
red := color.NRGBA{R: 180, G: 0, B: 0, A: 255}
circle := canvas.NewCircle(red)
circle.StrokeWidth = 4
circle.FillColor = red
c.SetContent(circle)
}
|
一个Widget是一个特殊的Canvas,一个Window可以设置一个单独的Widget.
1
2
3
4
5
6
7
|
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Widget")
myWindow.SetContent(widget.NewEntry())
myWindow.Resize(fyne.NewSize(500, 500))
myWindow.ShowAndRun()
}
|
Container和Layouts
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Container")
green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
text1 := canvas.NewText("Hello", green)
text2 := canvas.NewText("There", green)
text2.Move(fyne.NewPos(20, 20))
content := container.NewWithoutLayout(text1, text2)
myWindow.SetContent(content)
myWindow.Resize(fyne.NewSize(500, 500))
myWindow.ShowAndRun()
}
|
AppTabs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("TabContainer Widget")
text1 := canvas.NewText("1", color.White)
text2 := canvas.NewText("2", color.White)
text3 := canvas.NewText("3", color.White)
grid := container.New(layout.NewGridLayout(2), text1, text2, text3)
tabs := container.NewAppTabs(
container.NewTabItem("Tab 1", grid),
container.NewTabItem("Tab 2", widget.NewLabel("World!")),
)
//tabs.Append(container.NewTabItemWithIcon("Home", theme.HomeIcon(), widget.NewLabel("Home tab")))
tabs.SetTabLocation(container.TabLocationLeading)
myWindow.SetContent(tabs)
myWindow.ShowAndRun()
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("Button Widget")
content := widget.NewButton("click me", func() {
showWindow2(myApp)
})
//content := widget.NewButtonWithIcon("Home", theme.HomeIcon(), func() {
// log.Println("tapped home")
//})
myWindow.SetContent(content)
myWindow.ShowAndRun()
}
func showWindow2(app fyne.App) {
myWindow2 := app.NewWindow("Button Widget 2")
text := canvas.NewText("window2", color.White)
myWindow2.SetContent(text)
myWindow2.Show()
}
|
Entry(输入框)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("Entry Widget")
input := widget.NewEntry()
input.SetPlaceHolder("Enter text...")
content := container.NewVBox(input, widget.NewButton("Save", func() {
log.Println("Content was:", input.Text)
}), widget.NewButton("Cancel", func() {
log.Println("Content was cancel:", input.Text)
}))
myWindow.SetContent(content)
myWindow.ShowAndRun()
}
|
选择框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("Choice Widgets")
check := widget.NewCheck("Optional", func(value bool) {
log.Println("Check set to", value)
})
radio := widget.NewRadioGroup([]string{"Option 1", "Option 2"}, func(value string) {
log.Println("Radio set to", value)
})
combo := widget.NewSelect([]string{"Option 1", "Option 2"}, func(value string) {
log.Println("Select set to", value)
})
myWindow.SetContent(container.NewVBox(check, radio, combo))
myWindow.ShowAndRun()
}
|
表单提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("Form Widget")
entry := widget.NewEntry()
textArea := widget.NewMultiLineEntry()
form := &widget.Form{
Items: []*widget.FormItem{ // we can specify items in the constructor
{Text: "Entry", Widget: entry}},
OnSubmit: func() { // optional, handle form submission
log.Println("Form submitted:", entry.Text)
log.Println("multiline:", textArea.Text)
myWindow.Close()
},
}
// we can also append items
form.Append("Text", textArea)
myWindow.SetContent(form)
myWindow.ShowAndRun()
}
|
进度条
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
func main() {
// scr := gui.InitNewScreen()
// gui.Start(scr)
myApp := app.New()
myWindow := myApp.NewWindow("ProgressBar Widget")
progress := widget.NewProgressBar()
infinite := widget.NewProgressBarInfinite()
go func() {
for i := 0.0; i <= 1.0; i += 0.5 {
time.Sleep(time.Millisecond * 3000)
progress.SetValue(i)
progress.Hide()
infinite.Hide()
}
}()
myWindow.SetContent(container.NewVBox(progress, infinite))
myWindow.ShowAndRun()
}
|