关于 Fyne
Fyne 是使用 Go 语言编写的易于使用的 UI 工具包和应用程序 API。它旨在构建使用单个代码库在桌面和移动设备上运行的应用程序。
当前的版本是 1.2,该版本增加了对 iOS 和 Android 设备的支持,并提供了编写自定义窗口小部件的更简单方法。我们现在正在朝 1.3 迈进,它将添加数据绑定和一些更高级的小部件,例如表和列表。
使用条件
要使用 Fyne 开发应用,您将需要 Go 1.12 或更高版本。
设置好goproxy=https://goproxy.cn,采用go mod模式开发,可以自动下载依赖包。
编译注意事项
如果不带任何参数编译,fyne应用会先打开控制台窗口,然后才从控制台窗口打开应用。要取消启动时的控制台窗口,需要在编译时加入如下参数:-ldflags -H=windowsgui。如下:
go build -ldflags -H=windowsgui main.go
Helloworld示例:
1 package main
2
3 import "fyne.io/fyne/widget"
4 import "fyne.io/fyne/app"
5
6 func main() {
7 app := app.New()
8
9 w := app.NewWindow("Hello")
10 w.SetContent(widget.NewVBox(
11 widget.NewLabel("Hello Fyne!"),
12 widget.NewButton("Quit", func() {
13 app.Quit()
14 }),
15 ))
16
17 w.ShowAndRun()
18 }
运行效果:
一个更复杂的示例:
1 // Package main provides various examples of Fyne API capabilities
2 package main
3
4 import (
5 "fmt"
6 "net/url"
7
8 "fyne.io/fyne"
9 "fyne.io/fyne/app"
10 "fyne.io/fyne/canvas"
11 "fyne.io/fyne/cmd/fyne_demo/data"
12 "fyne.io/fyne/cmd/fyne_demo/screens"
13 "fyne.io/fyne/layout"
14 "fyne.io/fyne/theme"
15 "fyne.io/fyne/widget"
16 )
17
18 const preferenceCurrentTab = "currentTab"
19
20 func parseURL(urlStr string) *url.URL {
21 link, err := url.Parse(urlStr)
22 if err != nil {
23 fyne.LogError("Could not parse URL", err)
24 }
25
26 return link
27 }
28
29 func welcomeScreen(a fyne.App) fyne.CanvasObject {
30 logo := canvas.NewImageFromResource(data.FyneScene)
31 logo.SetMinSize(fyne.NewSize(228, 167))
32
33 return widget.NewVBox(
34 widget.NewLabelWithStyle("Welcome to the Fyne toolkit demo app", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
35 layout.NewSpacer(),
36 widget.NewHBox(layout.NewSpacer(), logo, layout.NewSpacer()),
37
38 widget.NewHBox(layout.NewSpacer(),
39 widget.NewHyperlink("fyne.io", parseURL("https://fyne.io/")),
40 widget.NewLabel("-"),
41 widget.NewHyperlink("documentation", parseURL("https://fyne.io/develop/")),
42 widget.NewLabel("-"),
43 widget.NewHyperlink("sponsor", parseURL("https://github.com/sponsors/fyne-io")),
44 layout.NewSpacer(),
45 ),
46 layout.NewSpacer(),
47
48 widget.NewGroup("Theme",
49 fyne.NewContainerWithLayout(layout.NewGridLayout(2),
50 widget.NewButton("Dark", func() {
51 a.Settings().SetTheme(theme.DarkTheme())
52 }),
53 widget.NewButton("Light", func() {
54 a.Settings().SetTheme(theme.LightTheme())
55 }),
56 ),
57 ),
58 )
59 }
60
61 func main() {
62 a := app.NewWithID("io.fyne.demo")
63 a.SetIcon(theme.FyneLogo())
64
65 w := a.NewWindow("Fyne Demo")
66 w.SetMainMenu(fyne.NewMainMenu(fyne.NewMenu("File",
67 fyne.NewMenuItem("New", func() { fmt.Println("Menu New") }),
68 // a quit item will be appended to our first menu
69 ), fyne.NewMenu("Edit",
70 fyne.NewMenuItem("Cut", func() { fmt.Println("Menu Cut") }),
71 fyne.NewMenuItem("Copy", func() { fmt.Println("Menu Copy") }),
72 fyne.NewMenuItem("Paste", func() { fmt.Println("Menu Paste") }),
73 )))
74 w.SetMaster()
75
76 tabs := widget.NewTabContainer(
77 widget.NewTabItemWithIcon("Welcome", theme.HomeIcon(), welcomeScreen(a)),
78 widget.NewTabItemWithIcon("Widgets", theme.ContentCopyIcon(), screens.WidgetScreen()),
79 widget.NewTabItemWithIcon("Graphics", theme.DocumentCreateIcon(), screens.GraphicsScreen()),
80 widget.NewTabItemWithIcon("Windows", theme.ViewFullScreenIcon(), screens.DialogScreen(w)),
81 widget.NewTabItemWithIcon("Advanced", theme.SettingsIcon(), screens.AdvancedScreen(w)))
82 tabs.SetTabLocation(widget.TabLocationLeading)
83 tabs.SelectTabIndex(a.Preferences().Int(preferenceCurrentTab))
84 w.SetContent(tabs)
85
86 w.ShowAndRun()
87 a.Preferences().SetInt(preferenceCurrentTab, tabs.CurrentTabIndex())
88 }
运行效果:
中文支持
首先,下载一个 TTF 格式的中文字库,可以下载思源字体的字库。需要注意的是,字库的格式必须是 TTF 的,否则会报错。
然后添加一个环境变量 FYNE_FONT,指定下载好的字库文件:
下面是一个查询网络IP属主的示例:
1 package main
2
3 import (
4 "fmt"
5 "fyne.io/fyne"
6 "fyne.io/fyne/app"
7 "fyne.io/fyne/theme"
8 "fyne.io/fyne/widget"
9 "fyne.io/fyne/layout"
10 "net/http"
11 "io/ioutil"
12 "encoding/json"
13 )
14
15 var ip = widget.NewLabel("")
16 var position = widget.NewLabel("")
17 var isp = widget.NewLabel("")
18
19 type IpInfo struct {
20 Code int `json:"code"`
21 Message string `json:"msg"`
22 Data `json:"data"`
23 }
24
25 type Data struct {
26 IP string `json:"ip"`
27 Position string `json:"pos"`
28 Isp string `json:"isp"`
29 }
30
31 func main() {
32 a := app.New()
33 a.Settings().SetTheme(theme.LightTheme())
34 w := a.NewWindow("Demo")
35 w.Resize(fyne.NewSize(600, 500))
36 w.SetContent(fyne.NewContainerWithLayout(layout.NewGridLayoutWithColumns(2), info(GetIpInfo("")), query()))
37 w.ShowAndRun()
38 }
39
40 func GetIpInfo(ip string) string {
41 if len(ip) == 0 {
42 return ""
43 }
44
45 url := fmt.Sprintf("http://v1.alapi.cn/api/ip?ip=%s&format=json", ip)
46
47 resp, err := http.Get(url)
48 if err != nil {
49 // handle error
50 }
51
52 defer resp.Body.Close()
53 body, err := ioutil.ReadAll(resp.Body)
54 if err != nil {
55 // handle error
56 }
57
58 return string(body)
59 }
60
61 func query() fyne.CanvasObject {
62 ip := widget.NewEntry()
63 ip.SetPlaceHolder("Please input IP address")
64
65 form := &widget.Form{
66 OnSubmit: func() {
67 info(GetIpInfo(ip.Text))
68 },
69 }
70
71 form.Append("IP", ip)
72 query := widget.NewGroup("Query", form)
73 return widget.NewScrollContainer(query)
74 }
75
76 func info(response string) fyne.CanvasObject {
77 var i IpInfo
78 json.Unmarshal([]byte(response),&i)
79
80 screen := widget.NewForm(
81 &widget.FormItem{Text: "IP地址:", Widget: ip},
82 &widget.FormItem{Text: "所属地:", Widget: position},
83 &widget.FormItem{Text: "供应商:", Widget: isp},
84 )
85
86 ip.SetText(i.IP)
87 position.SetText(i.Position)
88 isp.SetText(i.Isp)
89
90 info := widget.NewGroup("Info", screen)
91 return widget.NewScrollContainer(info)
92 }
运行效果如下:
来源:oschina
链接:https://my.oschina.net/u/4356413/blog/4376715