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 main
import (
"fyne.io/fyne/v2/app"
)
func main() {
//创建一个app
a:=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 main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
)
func main() {
//创建一个app
a:=app.New()
//创建一个window
w:=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 main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)
func main() {
//创建一个app
a:=app.New()
//创建一个window
w := 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 main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)
func main() {
//创建一个app
a:=app.New()
//创建一个window
w := 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() {
//创建一个app
a:=app.New()
//创建一个窗口
w:=a.NewWindow("my name is winodows title")
//设置初始窗口打下
w.Resize(fyne.NewSize(300,300))
//定义一个装置 checkbox组件
check:=widget.NewCheck("men", func(b bool) {
//勾选上 就为true
if b{
fmt.Println("我是男性")
check.Show()//显示
}else{
fmt.Println("我是女性")
check.Hide()//隐藏
}
})
//将装置添加到窗口
w.SetContent(check)
//运行
w.ShowAndRun()
}
check.Hide() //可将复选框隐藏
1.3.4 超链接hyperlink
超链接 点击即可实现跳转
//定义一个装置 hyperlink
url,_:=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
//定义一个组件 cards
widgetCard:=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.0
data:=binding.BindFloat(&f)
//滑动数据的组件 最小数据0 最大数据100 初始默认数为20
slider1:=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=s
label.Refresh()
})
w.SetContent(container.NewVBox(sel,label))
1.4 画布
1.4.1 修改文本颜色 Change color
显示有颜色的字
func main() {
//创建一个app
a:=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.Black
canvasCircle.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.Black
canvasRect.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.Black
canvasLine.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)
只能有一个参数,所以用个框装起来
水平:体现在两个组件之间位置关系
//创建一个按钮button
button:=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 rect
redRect:=canvas.NewRectangle(color.NRGBA{R: 255,G: 0,B: 0,A: 255})
redRect.SetMinSize(fyne.NewSize(200,200))
//blue rect
blueRect:=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作为图标
//指定你需要加载图片的url
r,_:=fyne.LoadResourceFromURLString("https://picsum.photos/200")
//设置app 图标
w.SetIcon(r)
1.8 菜单栏 menu
//设置menuitem相关信息
menuItem:=&fyne.Menu{
Label: "File",
Items: nil,
}
//根据item创建menu
menu:=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创建menu
newMenu:=fyne.NewMenu("File",menuItems1,menuItems2,menuItems3)
//创建主menu
menu:=fyne.NewMainMenu(newMenu)
//设置在窗口
w.SetMainMenu(menu)
创建多个并列**menu**
//创建多个item
newItem:=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)
//创建mainmenu
mainmenu:=fyne.NewMainMenu(menu1,menu2,menu3)
//设置在窗口上
w.SetMainMenu(mainmenu)
1.8.1 子菜单
//创建多个item
item1:=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)
//创建mainmenu
mainmenu:=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 main
import (
"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(){
//创建app
a:=app.New()
//创建一个windows
w:=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() {
//创建一个app
a:=app.New()
//创建一个windows
w:=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() {
//创建一个app
a:=app.New()
//创建一个windows
w:=a.NewWindow("my name is title")
//修改默认大小
w.Resize(fyne.NewSize(300,300))
//创建图片组件 初始显示1.png
canvasImg:=canvas.NewImageFromFile("C:/Users/jq/Desktop/dice/1.png")
//以原始图片样式显示 必须有
canvasImg.FillMode=canvas.ImageFillOriginal
//随机数种子
rand.Seed(time.Now().UnixNano())
//创建一个组件button
button:=widget.NewButton("run", func() {
//1-6
rand1:=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() {
//创建一个app
a:=app.New()
//创建一个windows
w:=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())
//假设密码长度为10
length := 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() {
//创建app
a:=app.New()
//创建一个windows
w:=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=ans
textAns.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
}