本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法
Go 1.16idegoland2021.2
2.Fyne总览
2.1 Canvas(画布) and CanvasObject
CanvasWindow.Canvas()CanvasWindowFyneCanvasObjectCanvas.SetContent()FillColourrect.Refresh()
package main
import (
"image/color"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)
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(100, 100))
myWindow.ShowAndRun()
}
我们可以用同样的方式绘制很多不同的绘图元素,比如圆形和文字。
func setContentToText(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: 0xff, G: 0x33, B: 0x33, A: 0xff}
circle := canvas.NewCircle(color.White)
circle.StrokeWidth = 4
circle.StrokeColor = red
c.SetContent(circle)
}
小部件(Widget)
fyne.WidgetWidgetRendererCanvasObjectwidget.Entry
package main
import (
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Widget")
myWindow.SetContent(widget.NewEntry())
myWindow.ShowAndRun()
}
2.2 Container and Layouts(容器和布局)
CanvasObjectCanvasContainerfyne.Containerfyne.CanvasObjectfyne.Canvascontainer.NewWithoutLayout()text2.Move()
fyne.Layoutcontainer.New()Layout list
2.3 小部件(Widget)列表
widget
手风琴(Accordion )
Accordion 显示 AccordionItems 列表。每个项目都由一个按钮表示,点击该按钮会显示详细视图。
按钮(Button)
按钮小部件具有文本标签和图标,两者都是可选的。
卡片(Card)
卡片小部件使用标题和子标题对元素进行分组,所有这些都是可选的。
复选框(Check )
检查小部件有一个文本标签和一个选中(或未选中)的图标。
输入框(Entry)
输入框小部件允许在获得焦点时输入简单的文本。
PasswordEntry 小部件隐藏文本输入并添加一个按钮来显示文本。
文件图标(FileIcon)
FileIcon 为各种类型的文件提供有用的标准图标。它将文件类型显示为指示器图标并显示文件类型的扩展名。
表单(Form)
表单小部件是两列网格,其中每一行都有一个标签和一个小部件(通常是一个输入)。最后一行将包含适当的表单控制按钮。
超链接(Hyperlink)
超链接小部件是具有适当填充和布局的文本组件。单击后,URL 将在您的默认 Web 浏览器中打开。
图标(Icon)
图标小部件是一个基本的图像组件,它加载其资源以匹配主题。
标签(Label )
标签小部件是具有适当填充和布局的标签组件。
进度条(ProgressBar)
ProgressBar 小部件创建一个指示进度的水平面板。
ProgressBarInfinite 小部件创建一个水平面板,指示无限进度条 0% -> 100% 重复循环,直到调用 Stop()。
单选框组(RadioGroup)
RadioGroup 小部件有一个文本标签列表和每个旁边的单选检查图标。
下拉选择框(Select)
选择小部件有一个选项列表,显示当前选项,并在单击时触发事件函数。
下拉选择框可输入选择(SelectEntry)
小部件将可编辑组件添加到下拉选择框小部件。用户可以选择一个选项或输入自己的值。
分割线(Separator)
分隔小部件显示其他元素之间的分界线。
滑块(Slider)
Slider小部件可以在两个固定值之间滑动切换。
文本网格(TextGrid )
TextGrid 是一个等宽的字符网格。这旨在供文本编辑器、代码预览或终端仿真器使用。
工具栏(Toolbar)
工具栏小部件创建工具按钮的水平列表。
widget
集成小部件提供高级缓存功能,以提供海量数据的高性能呈现。这确实导致了一个更复杂的构造函数,但是对于它实现的结果来说是一个很好的平衡。这些小部件中的每一个都使用一系列回调,最小集合由它们的构造函数定义,其中包括数据大小、可重复使用的模板的创建、数据应用于小部件的函数。
列表(List)
List 提供了许多子项的高性能垂直滚动。
表格(Table)
表格提供了许多子项的高性能滚动二维显示。
树(Tree)
树提供了一个高性能的垂直滚动项目,可以展开以显示子元素。
container
容器小部件类似于常规容器,但它们提供了一些额外的功能。
应用选项卡(AppTabs)
AppTabs 小部件允许从 TabItems 列表切换可见内容。每个项目都由小部件顶部的按钮表示。
滚动容器 (ScrollContainer)
ScrollContainer 定义了一个小于 Content 的容器。
分裂容器(SplitContainer)
SplitContainer 定义了一个容器,其大小在两个子项之间拆分。
2.4 布局(layout)列表
水平框(HBox)
水平框将项目排列在水平行中。每个元素都将具有相同的高度(容器中最高项目的高度),并且对象将在其最小宽度处左对齐。
垂直框 (VBox)
垂直框将项目排列在垂直列中。每个元素将具有相同的宽度(容器中最宽项的宽度),并且对象将在其最小高度处顶部对齐。
居中(Center )
居中布局将所有容器元素放置在容器的中心。每个对象都将设置为其最小尺寸。
表单布局(Form)
表单布局将项目成对排列,其中第一列的宽度最小。这对于在表单中标记元素通常很有用,其中标签位于第一列,而它描述的项目位于第二列。您应该始终向表单布局添加偶数个元素。
网格(Grid)
网格布局在可用空间中平均排列项目。指定了列数,对象水平放置,直到达到列数,此时新行开始。所有对象具有相同的大小,即宽度除以总列,高度将是总高度除以所需的行数。减去填充。
网格环绕(GridWrap)
GridWrap 布局将所有项目排列成一行,如果空间不足,则换行到新行。所有对象都将设置为相同的大小,即传递给布局的大小。此布局可能不尊重项目 MinSize 来管理此统一布局。通常用于文件管理器或图像缩略图列表。
边框(Border)
边框布局支持将项目定位在可用空间之外。边框被传递给(上、左、下、右)对象的指针。容器中未定位在边框上的所有项目将填充剩余空间。
最大(max)
最大布局定位所有容器元素以填充可用空间。这些对象都将是全尺寸的,并按照它们添加到容器中的顺序绘制(最后一个在顶部)。
填充(Padded)
填充布局定位所有容器元素以填充可用空间,但在外部有一个小填充。填充的大小是特定于主题的。所有对象都将按照它们添加到容器中的顺序绘制(最后一个在顶部)。
组合布局
可以嵌套多个容器,每个容器都有自己的布局,以仅使用上面列出的标准布局创建完整的用户界面排列。例如标题的水平框,左侧文件面板的垂直框和内容区域中的网格环绕布局 - 使用边框布局的所有容器内都可以构建如下所示的结果。
2.5 对话框(Dialog)列表
颜色
允许用户从标准集(或高级模式下的任何颜色)中选择一种颜色。
确认
询问动作的构象
文件打开
展示此内容以要求用户选择要在应用内使用的文件。实际显示的对话框取决于当前的操作系统。
表单
在对话框中获取各种输入元素,并进行验证。
信息
一种向应用程序用户呈现一些信息的简单方法。
通用
在对话框容器中呈现任何内容。
2.6 快捷方式
Window.Canvasfyne.ShortcutCopyShortcutdesktop.CustomShortcutTabControl
ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}
请注意,此快捷方式可以重复使用,因此您也可以将其附加到菜单或其他项目。对于此示例,我们希望它始终可用,因此我们将其注册到我们的窗口Canvas中,如下所示:
ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}
w.Canvas().AddShortcut(&ctrlTab, func(shortcut fyne.Shortcut) {
log.Println("We tapped Ctrl+Tab")
})
(Entry)TypedShortcutfyne.Shortcut
type myEntry struct {
widget.Entry
}
func (m *myEntry) TypedShortcut(s fyne.Shortcut) {
if _, ok := s.(*desktop.CustomShortcut); !ok {
m.Entry.TypedShortcut(s)
return
}
log.Println("Shortcut typed:", s)
}
TypedShortcut
2.7 使用[Preferences] API
存储用户配置和值是应用程序开发人员的一项常见任务,但跨多个平台实现它可能是乏味且耗时的。为了使它更容易,Fyne 有一个 API 用于在文件系统上以一种清晰易懂的方式存储值,同时为您处理复杂的部分。
让我们从 API 的设置开始。它是Preferences接口的一部分,其中存在 Bool、Float、Int 和 String 值的存储和加载函数。它们每个都包含三个不同的功能,一个用于加载,一个用于加载备用值,最后一个用于存储值。下面是 String 类型的三个函数及其行为的示例:
// String looks up a string value for the key
String(key string) string
// StringWithFallback looks up a string value and returns the given fallback if not found
StringWithFallback(key, fallback string) string
// SetString saves a string value for the given key
SetString(key string, value string)
Preferences()app.NewWithID()
a := app.NewWithID("com.example.tutorial.preferences")
[...]
a.Preferences().SetBool("Boolean", true)
number := a.Preferences().IntWithFallback("ApplicationLuckyNumber", 21)
expression := a.Preferences().String("RegularExpression")
[...]
timeouttime.Duration
var timeout time.Duration
"AppTimeout"
timeoutSelector := widget.NewSelect([]string{"10 seconds", "30 seconds", "1 minute"}, func(selected string) {
switch selected {
case "10 seconds":
timeout = 10 * time.Second
case "30 seconds":
timeout = 30 * time.Second
case "1 minute":
timeout = time.Minute
}
a.Preferences().SetString("AppTimeout", selected)
})
timeoutSelector
timeoutSelector.SetSelected(a.Preferences().StringWithFallback("AppTimeout", "10 seconds"))
goroutine
go func() {
time.Sleep(timeout)
a.Quit()
}()
最后,生成的代码应如下所示:
package main
import (
"time"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.NewWithID("com.example.tutorial.preferences")
w := a.NewWindow("Timeout")
var timeout time.Duration
timeoutSelector := widget.NewSelect([]string{"10 seconds", "30 seconds", "1 minute"}, func(selected string) {
switch selected {
case "10 seconds":
timeout = 10 * time.Second
case "30 seconds":
timeout = 30 * time.Second
case "1 minute":
timeout = time.Minute
}
a.Preferences().SetString("AppTimeout", selected)
})
timeoutSelector.SetSelected(a.Preferences().StringWithFallback("AppTimeout", "10 seconds"))
go func() {
time.Sleep(timeout)
a.Quit()
}()
w.SetContent(timeoutSelector)
w.ShowAndRun()
}
2.8 数据绑定
Fyne v2.0.0data/bindingAPINewStringBindInt(*int)WithDataBind()Unbind()StringLabel
package main
import (
"time"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.New()
w := a.NewWindow("Hello")
str := binding.NewString()
go func() {
dots := "....."
for i := 5; i >= 0; i-- {
str.Set("Count down" + dots[:i])
time.Sleep(time.Second)
}
str.Set("Blast off!")
}()
w.SetContent(widget.NewLabelWithData(str))
w.ShowAndRun()
}
2.9 编译选项
Fyne
go run -tags mobile main.go
hints