0%

fyne

fyne

fyne包结构划分

fyne将功能划分到多个子包中:

  • fyne.io/fyne:提供所有fyne应用程序代码共用的基础定义,包括数据类型和接口;
  • fyne.io/fyne/app:提供创建应用程序的 API;
  • fyne.io/fyne/canvas:提供Fyne使用的绘制 API;
  • fyne.io/fyne/dialog:提供对话框组件;
  • fyne.io/fyne/layout:提供多种界面布局;
  • fyne.io/fyne/widget:提供多种组件,fyne所有的窗体控件和交互元素都在这个子包中。

Window

Canvas

fyne应用程序中,所有显示元素都是绘制在画布(Canvas)上的。这些元素都是画布对象(CanvasObject)。调用Canvas.SetContent()方法可设置画布内容。Canvas一般和布局(Layout)容器(Container)一起使用。canvas子包中提供了一些基础的画布对象:

元素挂载到画布上

1
2
c := container.New(layout.NewGridLayout(1), rect, text, line, circle, image, raster, gradient)
w.SetContent(c)

CanvasObject

Rectangle矩形

1
canvas.NewRectangle(color.Black)

Text 文本

对齐方式

  • TextAlignLeading:左对齐;
  • TextAlignCenter:中间对齐;
  • TextAlignTrailing:右对齐。

字体样式

通过设置Text对象的TextStyle字段值,TextStyle是一个结构体:

1
2
3
4
5
type TextStyle struct {
Bold bool
Italic bool
Monospace bool
}
  • Bold:粗体;
  • Italic:斜体;
  • Monospace:系统等宽字体。

外部字体

通过设置环境变量FYNE_FONT为一个.ttf文件从而使用外部字体。

1
2
3
4
text := canvas.NewText("Hello Text", color.Black)

text.Alignment = fyne.TextAlignTrailing
text.TextStyle = fyne.TextStyle{Italic: true}

Line线

1
2
3
line := canvas.NewLine(color.Black)

line.StrokeWidth = 10

Circle圆

1
2
3
4
circle := canvas.NewCircle(color.Black)

circle.StrokeColor = color.Gray{0x99}
circle.StrokeWidth = 5

ImageFromResource图像

1
2
image := canvas.NewImageFromResource(theme.FileIcon())
image.FillMode = canvas.ImageFillOriginal

RasterWithPixels栅格与像素

1
2
3
4
5
6
7
raster := canvas.NewRasterWithPixels(
func(_, _, w, h int) color.Color {
return color.RGBA{uint8(rand.Intn(255)),
uint8(rand.Intn(255)),
uint8(rand.Intn(255)), 0xff}
},
)

Gradient渐变图

HorizontalGradient水平线性渐变

1
gradient := canvas.NewHorizontalGradient(color.Black, color.Transparent)

VerticalGradient垂直线性渐变

1
gradient := canvas.NewRadialGradient(color.Black, color.Transparent)

Widget

组件

窗体控件是一个Fyne应用程序的主要组成部分。它们能适配当前的主题,并且处理与用户的交互。

Label标签

标签(Label)用于显示字符串。

它有点类似于canvas.Text,不同之处在于Label可以处理简单的格式化比如’\n’

1
label := widget.NewLabel("Name")

Button按钮

按钮(Button)控件让用户点击,给用户反馈。

Button可以包含文本,图标或两者皆有。

调用widget.NewButton()创建一个默认的文本按钮,传入文本和一个无参的回调函数。

带图标的按钮需要调用widget.NewButtonWithIcon(),传入文本和回调参数,还需要一个fyne.Resource类型的图标资源:

Entry输入框

输入框(Entry)控件用于给用户输入简单的文本内容。

调用widget.NewEntry()即可创建一个输入框控件。

我们一般保存输入框控件的引用,以便访问其Text字段来获取内容。

  • 注册OnChanged回调函数。每当内容有修改时,OnChanged就会被调用。

    1
    2
    3
    nameEntry.OnChanged = func(content string) {
    fmt.Println("name:", nameEntry.Text, "entered")
    }
  • 调用SetReadOnly(true)设置输入框的只读属性。

  • SetPlaceHolder()用来设置占位字符串。

  • 设置字段Multiline让输入框接受多行文本。

  • 使用NewPasswordEntry()创建一个密码输入框,输入的文本不会以明文显示。

通常将Button与Entry结合使用

1
2
3
4
5
input := widget.NewEntry()
input.SetPlaceHolder("Enter text...")
content := container.NewVBox(input, widget.NewButton("Save", func() {
log.Println("Content was:", input.Text)
}))

Choices 选择框

Check是简单的选择框,每个选择是独立的,例如爱好可以是足球、篮球,也可以都是。创建方法widget.NewCheck(),传入选项字符串(足球,篮球)和回调函数。

回调函数接受一个bool类型的参数,表示该选项是否选中。

1
2
3
4
5
6
7
8
9
football := widget.NewCheck("football", func(value bool) {
fmt.Println("football:", value)
})
basketball := widget.NewCheck("basketball", func(value bool) {
fmt.Println("basketball:", value)
})
pingpong := widget.NewCheck("pingpong", func(value bool) {
fmt.Println("pingpong:", value)
})

CheckGroup支持由字符串切片快速生成多个选择框,回调函数接受一个[]string类型的参数,为当前所有勾选的Group内的选项

RadioGroup是单选框,每个组内只能选择一个,例如性别,只能是男或女(?)。创建方法widget.NewRadioGroup(),传入字符串切片和回调函数作为参数。回调函数接受一个字符串参数,表示选中的选项。也可以使用Selected字段读取选中的选项。

1
2
3
4
sexRadioGroup := widget.NewRadioGroup([]string{"male", "female", "unknown"}, func(value string) {
fmt.Println("sex:", value)
})
sexBox := container.NewHBox(widget.NewLabel("Sex"), sexRadioGroup)

Select是下拉选择框,点击时显示一个下拉菜单,点击选择。选项非常多的时候,比较适合用Select。创建方法widget.NewSelect(),参数与NewRadio()完全相同。

1
2
3
4
provinceSelect := widget.NewSelect([]string{"anhui", "zhejiang", "shanghai"}, func(value string) {
fmt.Println("province:", value)
})
provinceBox := container.NewHBox(widget.NewLabel("Province"), layout.NewSpacer(), provinceSelect)

From表单

表单控件(Form)用于对很多Label和输入控件进行布局。

如果指定了OnSubmitOnCancel函数,表单控件会自动添加对应的Button按钮。

1
2
3
4
5
6
form.OnSubmit = func() {
fmt.Println("name:", nameEntry.Text, "pass:", passEntry.Text, "login in")
}
form.OnCancel = func() {
fmt.Println("login canceled")
}

我们调用widget.NewForm()传入一个widget.FormItem切片创建Form控件。

1
2
3
4
form := widget.NewForm(
&widget.FormItem{Text: "Name", Widget: nameEntry},
&widget.FormItem{Text: "Pass", Widget: passEntry},
)

也可以通过&widget.Form{}创建

1
2
3
4
5
6
7
8
9
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()
},
}

每一项中一个字符串作为Label的文本,一个控件对象。

创建好Form对象之后还能调用其Append(label, widget)方法添加控件。有bug导致OnSubmitOnCancel函数不起作用,最好在New表单的时候就指定完所有的控件。

ProgressBar进度条控件

进度条控件(ProgressBar)用来表示任务的进度。

创建方法widget.NewProgressBar(),默认最小值为0.0,最大值为1.1,可通过Min/Max字段设置。

1
2
3
4
bar := widget.NewProgressBar()

bar.Min = 0
bar.Max = 100

调用SetValue()方法来控制进度。

1
bar.SetValue(float64(i))

还有一种进度条是循环动画,它表示有任务在进行中,并不能表示具体的完成情况。

1
bar := widget.NewProgressBarInfinite()

容器和布局

Box盒子

盒子控件(Box)就是一个简单的水平或垂直的容器。

在内部,Box对子控件采用盒状布局(Box Layout)。

我们可以通过传入控件对象给widget.NewHBox()widget.NewVBox()创建盒子。

或者调用已经创建好的widget.Box对象的Append()Prepend()向盒子中添加控件。前者在尾部追加,后者在头部添加。

它有两种变体,水平和垂直。方框布局将所有元素排列在一行或一列中,并带有可选的空格以帮助对齐。

用layout创建的水平框布局。NewHBoxLayout()创建单行中项目的排列。框中的每个项目都将其宽度设置为其MinSize()。所有项目的宽度和高度都将相等,这是所有MinSize().height值中的最大值。布局可以在容器中使用,也可以使用box小部件。NewHBox()。

1
2
3
4
5
6
7
8
content := container.New(
layout.NewHBoxLayout(),
...
)

或者

content := container.NewHBox()

垂直框布局类似,但它在列中排列项目。每个项目的高度将设置为最小值,所有宽度将相等,设置为最小宽度中的最大值。

要在元素之间创建扩展空间(例如,使一些元素左对齐,另一些元素右对齐),请添加layout.NewSpacer()作为其中一项。间隔件将展开以填充所有可用空间。在垂直框布局的开头添加间隔符将导致所有项目底部对齐。您可以在水平排列的起点和终点添加一个,以创建中心对齐。

1
centered := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), text4, layout.NewSpacer())

TabContainer标签容器

标签容器(TabContainer)允许用户在不同的内容面板之间切换。

标签可以是文本或图标。

使用container.NewAppTabs(…)和传递container.TabItem项(可以使用container.NewTabItem(…)创建)创建选项卡容器。

1
2
3
4
tabs := container.NewAppTabs(
container.NewTabItem("Profile", profile),
container.NewTabItem("Setting", setting),
)

可以通过设置选项卡的位置来配置选项卡容器,默认位置为top。

1
tabs.SetTabLocation(container.TabLocationBottom)
  • container.TabLocationTop
  • container.TabLocationBottom
  • container.TabLocationLeading
  • container.TabLocationTrailing

theme

家园图标

1
theme.HomeIcon()

活动流程

1
2
3
4
5
6
7
8
9
a := app.New()
w := a.NewWindow("")

//type1
w.ShowAndRun()

//type2
w.Show()
a.Run()

参考