fyne
fyne框架:https://github.com/fyne-io/fyne
对应文档:https://developer.fyne.io/
要使用 Fyne 开发应用程序,您需要 Go 版本 1.14 或更高版本、C 编译器和系统的开发工具(也即是gcc)
- 相应第三方库
$ go get fyne.io/fyne/v2 //fyne核心库
gcc编译工具我安装的是MInGW
地址:https://www.cnblogs.com/wustjq/p/16426471.html
1. 常用函数
1.1 窗口标题title
设置窗口标题
func (App)NewWindow(title string) Window 绑定在app一个方法
package mainimport ("fyne.io/fyne/v2/app")func main() {//创建一个appa:=app.New()//创建一个窗口w:=a.NewWindow("my frist title")//运行w.ShowAndRun()}

窗口大小可以随意调解
1.2 修改窗口默认大小Resize
修改默认窗口大小,只是修改了初始显示窗口大小,任然可以缩放大小
func (window)Resize(fyne.NewSize(w,h)) w—-width h——height
package mainimport ("fyne.io/fyne/v2""fyne.io/fyne/v2/app")func main() {//创建一个appa:=app.New()//创建一个windoww:=a.NewWindow("my title")//设置初始窗口大小w.Resize(fyne.NewSize(600,600))//运行w.ShowAndRun()}

1.3 组件 微件
1.3.1 标签 label text
创建一个小装置 微件
将创建的小装置添加到窗口
w.SetContent(widget.NewLabel("title label"))
package mainimport ("fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget")func main() {//创建一个appa:=app.New()//创建一个windoww := a.NewWindow("my title")//修改初始显示窗口大小w.Resize(fyne.NewSize(300,300))//widget:组件//新建一个标签组件w.SetContent(widget.NewLabel("title label"))//运行w.ShowAndRun()}

1.3.2 按钮button
//创建一个按钮button 第一个参数是button名字 第二个是点击就会对应执行的函数button:=widget.NewButton("my name is button", func() {})
package mainimport ("fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget")func main() {//创建一个appa:=app.New()//创建一个windoww := a.NewWindow("my title")//改变初始窗口大小w.Resize(fyne.NewSize(300,300))//创建一个按钮button组件button:=widget.NewButton("my name is button", func() {fmt.Println("button is pressed")})//将装置添加到窗口w.SetContent(button)//运行w.ShowAndRun()}

点击一次就会执行一次打印
1.3.2.1 button失效 disable
btn:=widget.NewButton("button", func() {fmt.Println("button is pressed")})//让button失效//btn.Disable()


1.3.2.2 给button设置背景色
//按钮btn:=widget.NewButton("visit", func() {})//按钮颜色btn_color:=canvas.NewRectangle(color.NRGBA{R: 255,G: 0,B: 0,A: 255})contain:=container.New(layout.NewMaxLayout(),//第一个是颜色btn_color,//第二个是按钮btn,//添加到窗口w.SetContent(contain)

使用图片做背景色
btn:=widget.NewButton("Visit", func() {})//图片来源img:=canvas.NewImageFromFile("C:/Users/jq/Desktop/bdyjy.jpg")img_contain:=container.New(layout.NewMaxLayout(),img,btn)//添加到窗口w.SetContent(contain)

1.3.3 复选框CheckBox
勾选上了 b就为真 没勾选上 b就为假
func main() {//创建一个appa:=app.New()//创建一个窗口w:=a.NewWindow("my name is winodows title")//设置初始窗口打下w.Resize(fyne.NewSize(300,300))//定义一个装置 checkbox组件check:=widget.NewCheck("men", func(b bool) {//勾选上 就为trueif b{fmt.Println("我是男性")check.Show()//显示}else{fmt.Println("我是女性")check.Hide()//隐藏}})//将装置添加到窗口w.SetContent(check)//运行w.ShowAndRun()}
check.Hide() //可将复选框隐藏

1.3.4 超链接hyperlink
超链接 点击即可实现跳转
//定义一个装置 hyperlinkurl,_:=url.Parse("https://www.cnblogs.com/wustjq/p/16426471.html")widgetUrl:=widget.NewHyperlink("my name is hyperlink",url)//添加至窗口w.SetContent(widgetUrl)

成功实现超链接跳转
1.3.5 图标 Icon
//定义一个装置 icon组件icon:=widget.NewIcon(theme.CancelIcon())//添加到窗口w.SetContent(icon)

1.3.6 cards
//定义一个组件 cardswidgetCard:=widget.NewCard("title","sub title",canvas.NewCircle(color.Black))//添加到窗口w.SetContent(widgetCard)

1.3.7 多行文本 multiline
multilineEntry:=widget.NewMultiLineEntry()const loren="The sunset and the solitary bird fly together, and the autumn water is the same color as the sky"multilineEntry.SetText(loren)
显示样式
multilineEntry.Wrapping=fyne.TextWrapBreak //不够换行显示

multilineEntry.Wrapping=fyne.TextWrapOff //一行显示

multilineEntry.Wrapping=fyne.TextTruncate

1.3.8 滑动数据 slider
f:=20.0data:=binding.BindFloat(&f)//滑动数据的组件 最小数据0 最大数据100 初始默认数为20slider1:=widget.NewSliderWithData(0.0,100.0,data)//根据数据创建label 将实时数据显示 如果没有这个label就看不到数据label1:=widget.NewLabelWithData(binding.FloatToString(data),)w.SetContent(container.NewVBox(slider1,label1))

1.3.9 登录提交 form
label:=widget.NewLabel("")form:=widget.NewForm(widget.NewFormItem("UserName",widget.NewEntry()),widget.NewFormItem("PassWord",widget.NewPasswordEntry()),)form.OnCancel= func() {label.Text="Cancel"label.Refresh()}form.OnSubmit= func() {label.Text="Submit"label.Refresh()}w.SetContent(container.NewVBox(form,label))

1.3.10 列表list
list:=widget.NewList(func() int {return 5}, //最终显示个数func() fyne.CanvasObject {return widget.NewLabel("")},func(id widget.ListItemID, object fyne.CanvasObject) {object.(*widget.Label).SetText("Hello World")}, //显示的内容)w.SetContent(list)

1.3.11 下拉框选择 select
label:=widget.NewLabel("")sel:=widget.NewSelect([]string{"one","two","three","four"}, func(s string) {fmt.Printf("selected is %s\n",s)label.Text=slabel.Refresh()})w.SetContent(container.NewVBox(sel,label))

1.4 画布
1.4.1 修改文本颜色 Change color
显示有颜色的字
func main() {//创建一个appa:=app.New()//创建一个窗口w:=a.NewWindow("my name is winodows title")//设置默认窗口打下w.Resize(fyne.NewSize(300,300))//画布里面创建文字canvasText:=canvas.NewText("canvas text",color.NRGBA{B: 255,G: 0,R: 0,A: 255})//设置文字字体大小canvasText.TextSize=30//添加到窗口w.SetContent(canvasText)//运行w.ShowAndRun()}

1.4.2 图片展示 image
//画布里面创建图片img:=canvas.NewImageFromFile("C:/Users/jq/Desktop/1.jpg")//添加到窗口w.SetContent(img)

1.4.3 圆 circle
//画布里面创建圆canvasCircle:=canvas.NewCircle(color.NRGBA{B: 255,G: 0,R: 0,A: 255})//边框颜色 边框线宽canvasCircle.StrokeColor=color.BlackcanvasCircle.StrokeWidth=3//添加到窗口w.SetContent(canvasCircle)

1.4.4 矩形 recttangle
//画布里面创建矩形canvasRect:=canvas.NewRectangle(color.NRGBA{B: 255,G: 0,R: 0,A: 255})//边框颜色 边框线宽canvasRect.StrokeColor=color.BlackcanvasRect.StrokeWidth=3//添加到窗口w.SetContent(canvasRect)

1.4.5 线 line
//画布里面创建线canvasLine:=canvas.NewLine(color.NRGBA{B: 255,G: 0,R: 0,A: 255})//边框颜色 边框线宽canvasLine.StrokeColor=color.BlackcanvasLine.StrokeWidth=3

1.4.6 颜色梯度变化gradient
//水平渐变canvas.NewHorizontalGradient(color.White,color.Black)//数值渐变canvas.NewVerticalGradient(color.White,color.Black)//以中心圆渐变canvas.NewRadialGradient(color.White,color.Black)参1:起始颜色 参2 终止颜色//一定角度渐变canvas.NewLinearGradient(color.White,color.Black,45)参1:起始颜色 参2 终止颜色 参3 角度
//画布里面创建梯度canvasgradient:=canvas.NewHorizontalGradient(color.White,color.Black)//添加到窗口w.SetContent(canvasgradient)

1.5 容器container
1.5.1 水平 竖直框
将多个组件装在一起显示
w.SetContent(newHBox)只能有一个参数,所以用个框装起来
水平:体现在两个组件之间位置关系
//创建一个按钮buttonbutton:=widget.NewButton("my name is button", func() {})//新建一个标签label:=widget.NewLabel("my name is label")//水平box将两个组件装起来newHBox:=container.NewHBox(button,label)//显示在窗口w.SetContent(newHBox)

1.5.2 水平 竖直隔离框
//画布中创建文本labels1:=canvas.NewText("text1",color.Black)labels2:=canvas.NewText("text2",color.Black)//创建一个标签组件w1:=widget.NewLabel("widget label")//添加到窗口w.SetContent(container.NewVSplit(container.NewHSplit(labels1,labels2),w1))

先是labels1和labels2在水平方向隔离,然后他们整体又再竖直方向和w1进行隔离
1.5.3 水平 竖直滚动框
//red rectredRect:=canvas.NewRectangle(color.NRGBA{R: 255,G: 0,B: 0,A: 255})redRect.SetMinSize(fyne.NewSize(200,200))//blue rectblueRect:=canvas.NewRectangle(color.NRGBA{R: 0,G: 0,B: 255,A: 255})blueRect.SetMinSize(fyne.NewSize(200,200))c:=container.NewVBox(redRect,blueRect)//创建scroll 滚动框scroll:=container.NewScroll(c)//显示在窗口w.SetContent(scroll)

1.6 修改主题颜色
a.Settings().SetTheme(theme.LightTheme()) //设置亮色主题a.Settings().SetTheme(theme.DarkTheme()) //设置暗色主题
//文字说明label:=widget.NewLabel("Fyne Theme")//亮色主题btn1:=widget.NewButton("Light Theme", func() {a.Settings().SetTheme(theme.LightTheme())})//暗色主题btn2:=widget.NewButton("Dark Theme", func() {a.Settings().SetTheme(theme.DarkTheme())})//退出btn3:=widget.NewButton("Exit", func() {a.Quit()})//添加到窗口w.SetContent(container.NewVBox(label,btn1,btn2,btn3))


1.7 设置窗口图标
1.使用fyne默认图标
//设置app 图口默认图标w.SetIcon(theme.FyneLogo())

2.加载本地图片做图标
//指定你需要加载图片路径r,_:=fyne.LoadResourceFromPath("./bdyjy.jpg") //相对路径和绝对路径都可//设置app 图标w.SetIcon(r)

3.从网上指定图片url作为图标
//指定你需要加载图片的urlr,_:=fyne.LoadResourceFromURLString("https://picsum.photos/200")//设置app 图标w.SetIcon(r)

1.8 菜单栏 menu
//设置menuitem相关信息menuItem:=&fyne.Menu{Label: "File",Items: nil,}//根据item创建menumenu:=fyne.NewMainMenu(menuItem)//在窗口显示w.SetMainMenu(menu)
创建多个**item**子项
//点击每个item执行相应的回调menuItems1:=fyne.NewMenuItem("New", func() {fmt.Println("New is pressed")})menuItems2:=fyne.NewMenuItem("Save", func() {fmt.Println("Save is pressed")})menuItems3:=fyne.NewMenuItem("Edit", func() {fmt.Println("Edit is pressed")})//根据item创建menunewMenu:=fyne.NewMenu("File",menuItems1,menuItems2,menuItems3)//创建主menumenu:=fyne.NewMainMenu(newMenu)//设置在窗口w.SetMainMenu(menu)

创建多个并列**menu**
//创建多个itemnewItem:=fyne.NewMenuItem("New",nil)editItem:=fyne.NewMenuItem("Edit",nil)saveItem:=fyne.NewMenuItem("Save",nil)//创建menu 这个相当于是折叠起来先显示的menu1:=fyne.NewMenu("File",newItem,editItem,saveItem)menu2:=fyne.NewMenu("Config",newItem,editItem,saveItem)menu3:=fyne.NewMenu("Content",newItem,editItem,saveItem)//创建mainmenumainmenu:=fyne.NewMainMenu(menu1,menu2,menu3)//设置在窗口上w.SetMainMenu(mainmenu)

1.8.1 子菜单
//创建多个itemitem1:=fyne.NewMenuItem("New",nil)item2:=fyne.NewMenuItem("Edit",nil)item3:=fyne.NewMenuItem("Save",nil)item2.ChildMenu=fyne.NewMenu("",fyne.NewMenuItem("Add",nil),fyne.NewMenuItem("Sub",nil),fyne.NewMenuItem("Div",nil),)//创建menu 这个相当于是折叠起来先显示的menu:=fyne.NewMenu("File",item1,item2,item3)//创建mainmenumainmenu:=fyne.NewMainMenu(menu)//设置在窗口上w.SetMainMenu(mainmenu)

1.9 对话框dialog
1.9.1 打开文件
btn:=widget.NewButton("Open .txt files", func() {//使用对话框打开文件//第一个参数是函数体,第二个参数是父窗口file_dial:=dialog.NewFileOpen(func(r fyne.URIReadCloser, err error) {//读取文件data,_:=ioutil.ReadAll(r)//得到结果result:=fyne.NewStaticResource("name",data)//展示文本在标签entry:=widget.NewMultiLineEntry()entry.SetText(string(result.StaticContent))//显示 title就设置为文件名,w:=fyne.CurrentApp().NewWindow(string(result.StaticName))w.SetContent(container.NewVBox(entry))w.Show()},w)//进行过滤file_dial.SetFilter(storage.NewExtensionFileFilter([]string{".txt"}))file_dial.Show()})w.SetContent(container.NewVBox(btn))


1.9.2 存储文件
entry:=widget.NewMultiLineEntry()//创建按钮用来储存文件btn:=widget.NewButton("Save .txt file", func() {//第一个是个函数 第二个是父窗口fileDialog:=dialog.NewFileSave(func(wc fyne.URIWriteCloser, err error) {//从输入获取数据信息data:=entry.Text//写到文件去wc.Write([]byte(data))},w)//设置文件名fileDialog.SetFileName("anyFileName.txt")fileDialog.Show()fileDialog.Refresh()})//窗口显示w.SetContent(container.NewVBox(entry,btn))


1.9.3 显示图片
btn:=widget.NewButton("Open .jpg & .png", func() {fileDialog:=dialog.NewFileOpen(func(r fyne.URIReadCloser, err error) {data,_:=ioutil.ReadAll(r)res:=fyne.NewStaticResource(r.URI().Name(),data)img:=canvas.NewImageFromResource(res)win:=fyne.CurrentApp().NewWindow(r.URI().Name())win.SetContent(img)win.Resize(fyne.NewSize(500,500))win.Show()},w)fileDialog.SetFilter(storage.NewExtensionFileFilter([]string{".jpg",".png"}))fileDialog.Show()})w.SetContent(btn)


1.10 组件位置大小约束
btn:=widget.NewButton("Button", func() {})btn.Resize(fyne.NewSize(40,100))btn.Move(fyne.Position{0,0})red_Rect:=canvas.NewRectangle(color.NRGBA{R: 255,G: 0,B: 0,A: 255})red_Rect.Resize(fyne.NewSize(40,100))red_Rect.Move(fyne.Position{250,250})blue_cicle:=canvas.NewCircle(color.NRGBA{0,255,0,255})blue_cicle.Resize(fyne.NewSize(40,100))blue_cicle.Move(fyne.Position{350,80})//这里一定要选择NewWithoutLayout 无布局方式 不然我们设置的位置大小都无效w.SetContent(container.NewWithoutLayout(btn,red_Rect,blue_cicle))

fmt.Println("blue_cicle:",blue_cicle.Position()) //可打印当前组件所在位置,以左上为基准
1.11 fyne不支持中文问题
方法1
借助第三方库:github.com/flopp/go-findfont
在init函数中完成初始化
package mainimport ("fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget""github.com/flopp/go-findfont""os""strings")func init() {fontPaths := findfont.List()for _, path := range fontPaths {//楷体 "simkai.ttf"//黑体 "simhei.ttf"if strings.Contains(path, "simkai.ttf") {os.Setenv("FYNE_FONT",path)break}}}func main(){//创建appa:=app.New()//创建一个windowsw:=a.NewWindow("我是窗口")w.Resize(fyne.NewSize(500,500))label:=widget.NewLabel("这是标签")w.SetContent(label)//运行w.ShowAndRun()}

方法2
- 将
C:\Windows\Fonts下选择合适的字体复制到你的项目路径下

- 使用init函数,设置环境变量即可使用
func init() {os.Setenv("FYNE_FONT","msyhl.ttc")}

1.15 小案例
案例1: 实现随机数
实现一个点击产生随机数
func main() {//创建一个appa:=app.New()//创建一个windowsw:=a.NewWindow("my name is title")//修改默认大小w.Resize(fyne.NewSize(300,300))//添加随机数种子 避免伪随机rand.Seed(time.Now().UnixNano())//新建一个标签label:=widget.NewLabel("my name is label")//创建一个按钮button 只要点击按钮就回触发回调函数button:=widget.NewButton("Generate", func() {//产生0-99随机数rand1:=rand.Intn(100)//相当于将label标签的文本覆盖label.Text=fmt.Sprint(rand1)//实时刷新label.Refresh()})//水平box将两个微件装起来newHBox:=container.NewVBox(button,label)//显示在窗口w.SetContent(newHBox)//运行w.ShowAndRun()}

案例2: 随机点数图片
func main() {//创建一个appa:=app.New()//创建一个windowsw:=a.NewWindow("my name is title")//修改默认大小w.Resize(fyne.NewSize(300,300))//创建图片组件 初始显示1.pngcanvasImg:=canvas.NewImageFromFile("C:/Users/jq/Desktop/dice/1.png")//以原始图片样式显示 必须有canvasImg.FillMode=canvas.ImageFillOriginal//随机数种子rand.Seed(time.Now().UnixNano())//创建一个组件buttonbutton:=widget.NewButton("run", func() {//1-6rand1:=rand.Intn(6)+1//修改图片路径canvasImg.File=fmt.Sprintf("C:/Users/jq/Desktop/dice/%d.png",rand1)//刷新canvasImg.Refresh()})//创建竖直box容器vBox:=container.NewVBox(canvasImg,button)//在窗口显示w.SetContent(vBox)//运行w.ShowAndRun()}

案例3: 随机颜色生成
func main() {//创建一个appa:=app.New()//创建一个windowsw:=a.NewWindow("my name is title")//修改默认大小w.Resize(fyne.NewSize(300,300))//播种随机数rand.Seed(time.Now().UnixNano())//画图创建矩形 默认初始是黑色rect:=canvas.NewRectangle(color.NRGBA{R: 0,G: 0,B: 0,A: 255})rect.SetMinSize(fyne.NewSize(150,150))//随机颜色btn1:=widget.NewButton("Ranndom Color", func() {//点击按钮 就会触发func ,将填充颜色进行修改rect.FillColor=color.NRGBA{R: uint8(rand.Intn(255)),B: uint8(rand.Intn(255)),G: uint8(rand.Intn(255)),A: 255}rect.Refresh()})//随机红色btnRed:=widget.NewButton("Ranndom Red", func() {rect.FillColor=color.NRGBA{R: uint8(rand.Intn(255)),B:0,G: 0,A: 255}rect.Refresh()})//随机绿btnGreen:=widget.NewButton("Ranndom Green", func() {rect.FillColor=color.NRGBA{R: 0,B:0,G: uint8(rand.Intn(255)),A: 255}rect.Refresh()})//随机蓝色btnBlue:=widget.NewButton("Ranndom Blue", func() {rect.FillColor=color.NRGBA{R: 0,B:uint8(rand.Intn(255)),G: 0,A: 255}rect.Refresh()})w.SetContent(container.NewVBox(rect,btn1,btnRed,btnBlue,btnGreen))//运行w.ShowAndRun()}

案例4:随机密码生成器
首先如何生成密码
func main() {rand.Seed(time.Now().UnixNano())//假设密码长度为10length := 10//数字strNum:="0123456789"//小写strLow:="abcdefghijklmnopqrstuvwxyz"//大写strUp:="ABCDEFGHIJKLMNOPQRSTUVWSYZ"//最后结果ans:=""//总共循环指定密码长度次数for i:=0;i<length;i++{//随机选择数字 小写 大写 根据不同case 在随机生成出一个字母 加在ans上randstr:=rand.Intn(3)switch randstr {case 0:rand1:=rand.Intn(len(strNum))ans+=string(strNum[rand1])case 1:rand2:=rand.Intn(len(strLow))ans+=string(strLow[rand2])case 2:rand3:=rand.Intn(len(strUp))ans+=string(strUp[rand3])}}}
最后实现:
func main() {//创建appa:=app.New()//创建一个windowsw:=a.NewWindow("Rand Code")//修改默认大小w.Resize(fyne.NewSize(300,300))title:=canvas.NewText("Password Generator",color.Black)//客户输入密码长度的位置input:=widget.NewEntry()input.SetPlaceHolder("Enter Password length")//生成结果的位置 初始结果为空textAns:=canvas.NewText("",color.Black)textAns.TextSize=20//运行的按钮btn:=widget.NewButton("Generate", func() {//获取输入的数字结果,转成int类型length,_:=strconv.Atoi(input.Text)//验证码ans:=RandGenCode(length)textAns.Text=anstextAns.Refresh()})w.SetContent(container.NewVBox(title,input,textAns,btn))//运行w.ShowAndRun()}func RandGenCode(length int)(ans string){rand.Seed(time.Now().UnixNano())//数字strNum:="0123456789"//小写strLow:="abcdefghijklmnopqrstuvwxyz"//大写strUp:="ABCDEFGHIJKLMNOPQRSTUVWSYZ"for i:=0;i<length;i++{randstr:=rand.Intn(3)switch randstr {case 0:rand1:=rand.Intn(len(strNum))ans+=string(strNum[rand1])case 1:rand2:=rand.Intn(len(strLow))ans+=string(strLow[rand2])case 2:rand3:=rand.Intn(len(strUp))ans+=string(strUp[rand3])}}return ans}

