登录
原创

go-fyne GUI开发组件集合

专栏go-fyne GUI开发
发布于 2023-08-02 阅读 7018
  • 后端
  • Go
原创

组件示例集合

Label 标签

小部件是Fyne桌面应用程序GUI的主要组件,可以在任何地方使用fyne.CanvasObject。它们管理用户交互,并始终与当前主题相匹配。

Label小部件是其中最简单的—它向用户显示文本。不像canvas.Text它可以处理一些简单的文本格式(如\n)和换行(通过设置Wrapping字段)。您可以通过调用widget来创建标签widget.NewLabel(“some text”),结果可以赋值给变量或直接传递到容器中。

// label
	label := widget.NewLabel("This is Widget.NewLable")
	text := canvas.NewText("canvas.NewText ", color.Black)

button

按钮小部件可以包含文本、图标或两者,构造函数是widget.NewButton()和widget. NewButtonWithIcon()。要创建一个文本按钮,只有两个参数,字符串内容和一个0参数func(),当按钮被点击时将被调用。请参阅示例,了解如何创建它。

带有图标的按钮构造函数包含一个额外的参数,fyne.Resource。主题包内的内置图标都能适当地适应主题的变化。如果传递本地图片资源可以使用fyne.LoadResourceFromPath()进行加载
如果要创建一个只有一个图标的按钮,你应该将label参数为空widget.NewButtonWithIcon()。

	// button
	btn := widget.NewButtonWithIcon("save", theme.DocumentSaveIcon(), func() {
		fmt.Println("print")
	})

entry 输入框

输入框部件用于用户输入简单的文本内容。可以使用一个简单的widget.NewEntry()构造函数创建。在创建小部件时,返回一个引用,以便以后可以访问它的Text字段。也可以使用OnChanged回调函数,以便每次内容更改时都收到通知。

条目小部件还可以具有验证功能,用于验证输入到其中的文本输入。这可以通过将Validator字段设置为fne . stringvalidator来实现。您还可以设置占位符文本,并将条目设置为MultiLine以接受多行文本。

// 文本框
	// entryStr := ""
	entry := widget.NewEntry()
	// 文本内容变更处理
	entry.OnChanged = func(val string) {
		fmt.Println(val)
	}

	// 文本内容校验
	entry.Validator = func(value string) error {
		_, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return errors.New("Invalid input. Please enter a numeric value.")
		}
		return nil
	}

	// 监听校验结果,
	entry.SetOnValidationChanged(func(e error) {
		if e != nil {
			fmt.Println("SetOnValidationChanged", e.Error())
		} else {
			fmt.Println("----true")
		}
	})

	// 添加提示
	entry.SetPlaceHolder("widget.NewEntry")
	btn.Resize(fyne.NewSize(100, 30))

	// 密码框
	pwd := widget.NewPasswordEntry()
	pwd.SetPlaceHolder("widget.NewPasswordEntry")

Choices 选择框:check、radio、select

有各种各样的小部件可以为用户提供选择,包括复选框、单选组和选择弹出框。

widget.Check提供了一个简单的yes/no选项,并使用字符串标签创建。这些小部件中的每一个还接受一个“已更改”的函数(…),其中参数是适当类型的。因此,widget.NewCheck(…)接受一个字符串参数作为标签,接受一个func(bool)参数作为更改处理程序。您还可以使用Checked字段来获取布尔值。

Radio单选框与此类似,但第一个参数是表示每个选项的字符串切片。这次change函数期望一个字符串参数返回当前选择的值。调用widget.NewRadioGroup(…)来构造radio组小部件,稍后您可以使用该引用来读取Selected字段,而不是使用更改回调。

选择小部件的构造函数签名与无线电小部件相同。调用widget.NewSelect(…)将显示一个按钮,当点击该按钮时,该按钮将显示一个弹出窗口,用户可以从中进行选择。对于很长的选项列表,这更合适。

 // check
	ck := widget.NewCheck("check1", func(val bool) {
		fmt.Println("check set to ", val)
	})
	rd := widget.NewRadioGroup([]string{"Option-1", "Option-2"}, func(val string) {
		fmt.Println("radio set to ", val)
	})
	sl := widget.NewSelect([]string{"select-1", "select-2", "select-3"}, func(val string) {
		fmt.Println("select set to ", val)
	})

	slk := container.NewHBox(ck, rd, sl)

Form 表单

表单小部件用于布局带有标签和可选的取消和提交按钮的许多输入字段。在最简单的形式中,它将标签对齐到每个输入小部件的左侧。通过设置OnCancel或OnSubmit,表单将添加一个按钮栏,并在适当的时候调用指定的处理程序。

小部件可以通过widget.NewForm(…)传递一个小部件列表来创建widget.FormItems,或者使用&widget.Form{}。示例中说明的Form{}语法。还有一个有用Form.Append(label, widget)。可用于替代语法的追加(标签、小部件)。

在这个例子中,我们创建了两个条目,其中一个是“multiline”(类似于HTML TextArea)来保存值。有一个OnSubmit处理程序,它在关闭窗口(以及应用程序)之前打印信息。

  formEntry1 := widget.NewEntry()
	formEntry1.SetPlaceHolder("formEntry1:=widget.NewEntry()")

	formEntry2 := widget.NewEntry()
	formEntry2.SetPlaceHolder("formEntry2:=widget.NewEntry()")

	// check

	fck := widget.NewCheck("check1", func(val bool) {
		fmt.Println("form check set to ", val)
	})
	frd := widget.NewRadioGroup([]string{"Option-1", "Option-2"}, func(val string) {
		fmt.Println("form radio set to ", val)
	})
	fsl := widget.NewSelect([]string{"select-1", "select-2", "select-3"}, func(val string) {
		fmt.Println("form select set to ", val)

	})
	fslk := container.NewHBox(fck, frd, fsl)

	form := &widget.Form{
		Items: []*widget.FormItem{
			{Text: "Entry", Widget: formEntry1},
			{Text: "Entry", Widget: formEntry2},
		},
		OnSubmit: func() {
			fmt.Println("Form submit:", formEntry2.Text)
			fmt.Println("Form submit:", formEntry1.Text)
			fmt.Println("Form check:", fck, frd, fsl)
			myWindow.Close()
		},
	}

	// 动态
	form.Append("Check", fslk)


进度条

	bar := widget.NewProgressBar()
	go func() {
		for i := 0.0; i < 1.01; i += 0.01 {
			time.Sleep(time.Millisecond * 300)
			bar.SetValue(i)
		}
	}()

数据绑定

数据双向binding

    
 // 声明绑定变量
	str := binding.NewString()
	str.Set("Hi!")
// 变量使用的时候用withData进行绑定,当str变更的时候,组件的内容会自动变更
	widget.NewLabelWithData(str),
	widget.NewEntryWithData(str),

list 组件

注意如果要让list全部显示,需要将其布局在border的middle或max中,

	// // 创建一个数据列表的绑定
	dataB := binding.BindStringList(&[]string{"item-1", "item-2"})
	tabel2 := widget.NewListWithData(dataB,
		func() fyne.CanvasObject {
			return widget.NewLabel("binding.NewStringList")
		}, func(i binding.DataItem, o fyne.CanvasObject) {
			o.(*widget.Label).Bind(i.(binding.String))
		})

示例演示

image.png

package main

import (
	"errors"
	"fmt"
	"image/color"
	"strconv"
	"strings"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/theme"

	"fyne.io/fyne/v2/widget"
)

func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("TabContainer Widget")
	myWindow.SetTitle("Widget Demo 300x300")

	// label
	label := widget.NewLabel("This is Widget.NewLable")
	text := canvas.NewText("canvas.NewText ", color.Black)

	// button
	btn := widget.NewButtonWithIcon("save", theme.DocumentSaveIcon(), func() {
		fmt.Println("print")
	})

	// 文本框
	// entryStr := ""
	entry := widget.NewEntry()
	// 文本内容变更处理
	entry.OnChanged = func(val string) {
		fmt.Println(val)
	}

	// 文本内容校验
	entry.Validator = func(value string) error {
		_, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return errors.New("Invalid input. Please enter a numeric value.")
		}
		return nil
	}

	// 监听校验结果,
	entry.SetOnValidationChanged(func(e error) {
		if e != nil {
			fmt.Println("SetOnValidationChanged", e.Error())
		} else {
			fmt.Println("----true")
		}
	})

	// 添加提示
	entry.SetPlaceHolder("widget.NewEntry")
	btn.Resize(fyne.NewSize(100, 30))

	// 密码框
	pwd := widget.NewPasswordEntry()
	pwd.SetPlaceHolder("widget.NewPasswordEntry")

	// check
	ck := widget.NewCheck("check1", func(val bool) {
		fmt.Println("check set to ", val)
	})
	rd := widget.NewRadioGroup([]string{"Option-1", "Option-2"}, func(val string) {
		fmt.Println("radio set to ", val)
	})
	sl := widget.NewSelect([]string{"select-1", "select-2", "select-3"}, func(val string) {
		fmt.Println("select set to ", val)
	})

	slk := container.NewHBox(ck, rd, sl)

	formEntry1 := widget.NewEntry()
	formEntry1.SetPlaceHolder("formEntry1:=widget.NewEntry()")

	formEntry2 := widget.NewEntry()
	formEntry2.SetPlaceHolder("formEntry2:=widget.NewEntry()")

	// check

	fck := widget.NewCheck("check1", func(val bool) {
		fmt.Println("form check set to ", val)
	})
	frd := widget.NewRadioGroup([]string{"Option-1", "Option-2"}, func(val string) {
		fmt.Println("form radio set to ", val)
	})
	fsl := widget.NewSelect([]string{"select-1", "select-2", "select-3"}, func(val string) {
		fmt.Println("form select set to ", val)

	})
	fslk := container.NewHBox(fck, frd, fsl)

	form := &widget.Form{
		Items: []*widget.FormItem{
			{Text: "Entry", Widget: formEntry1},
			{Text: "Entry", Widget: formEntry2},
		},
		OnSubmit: func() {
			fmt.Println("Form submit:", formEntry2.Text)
			fmt.Println("Form submit:", formEntry1.Text)
			fmt.Println("Form check:", fck, frd, fsl)
			myWindow.Close()
		},
	}

	// 动态
	form.Append("Check", fslk)

	// 进度条
	bar := widget.NewProgressBar()
	inf := widget.NewProgressBarInfinite()
	go func() {
		for i := 0.0; i < 1.01; i += 0.01 {
			time.Sleep(time.Millisecond * 300)
			bar.SetValue(i)
		}
	}()

	// 工具栏
	toolbar := widget.NewToolbar(
		widget.NewToolbarAction(theme.ComputerIcon(), func() {
			fmt.Println("widget.NewToolbarAction-ComputerIcon")
		}),
		widget.NewToolbarAction(theme.DocumentCreateIcon(), func() {
			fmt.Println("widget.NewToolbarAction-DocumentCreateIcon")
		}),
		widget.NewToolbarSeparator(),
		widget.NewToolbarAction(theme.ContentCopyIcon(), func() {
			fmt.Println("copy")
		}),
	)
	var data = []string{"a", "string", "list"}
	list := widget.NewList(func() int {
		return len(data)

	}, func() fyne.CanvasObject {
		return widget.NewLabel("list template")
	}, func(i widget.ListItemID, o fyne.CanvasObject) {
		o.(*widget.Label).SetText(data[i])
	},
	)
	fmt.Println("----", list.Length(),list.CreateItem())

	inpt:=widget.NewEntry()
	inpt.OnChanged = func(value string){
		if strings.Contains(value,"add") {
			fmt.Println("add list item")
			list.CreateItem()
		} else {
			fmt.Println("update list item")
			list.UpdateItem(1,widget.NewLabel("update "))

		}
		list.Refresh()
	}

	datat:= [][]string{[]string{"r1c1","r1c2"},[]string{"r2","c2"}}

	tabe:= widget.NewTable(

		func() (int,int) { return len(datat),len(datat[0])},
		func() fyne.CanvasObject{
			return widget.NewLabel("we")
		},
		func(i widget.TableCellID,o fyne.CanvasObject){
			o.(*widget.Label).SetText(datat[i.Row][i.Col])
		},
	)

	// // 创建一个数据列表的绑定
	// dataB := binding.NewStringList()
	dataB := binding.BindStringList(&[]string{"item-1","item-2"})
	tabel := widget.NewListWithData(dataB,
		func() fyne.CanvasObject {
			return widget.NewLabel("binding.NewStringList")
		}, func(i binding.DataItem, o fyne.CanvasObject) {
			o.(*widget.Label).Bind(i.(binding.String))
		})
	tabel.ScrollToBottom()
	btn9 := widget.NewButton("add item", func() {
		val := fmt.Sprintf("Item %d", dataB.Length()+1)
		dataB.Append(val)
	})

	ct := container.NewBorder(toolbar, nil, nil, nil, container.NewVBox(label, text, entry, pwd, slk, btn, form, bar, inf, list,inpt,tabe,tabel,btn9))
	myWindow.SetContent(ct)

	myWindow.Resize(fyne.NewSize(400, 1024))
	myWindow.ShowAndRun()
}

评论区

励志做一条安静的咸鱼,从此走上人生巅峰。

0

0

0

举报