go语言gui窗口应用之fyne框架-自定义容器实现自定义布局,更灵活的显示控件
一、自定义容器
在fyne中,所有的容器都是通过container
包下的New
函数定义的,先看源码:
package fyne
// 根据布局创建容器
func New(layout fyne.Layout, objects ...fyne.CanvasObject) *fyne.Container {
return &fyne.Container{Layout: layout, Objects: objects}
}
二、自定义布局
通过上述,可以看出,要实现自定义容器,关键是自定义布局,在 fyne 中,自定义布局,只要实现fyne
包下Layout
接口即可,以下为Layout
接口源码:
package fyne
// 布局接口
type Layout interface {
// 通过遍历[]CanvasObject,获取每个控件,设置每个控件大小和位置
Layout([]CanvasObject, Size)
// 设置容器总大小(宽,高)
MinSize(objects []CanvasObject) Size
}
三、我的自定义容器代码
- 注意:自定义容器中控件宽、高,可能受自定义容器的外部容器影响,修改控件宽、高时,可能没有效果,需要对外部容器也要做相应操作。
- 可以通过查看
fyne
中container
源码定义的布局,扩充自定义布局功能。
以下是我简易布局代码:
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
)
// 自定义容器,按照控件实际大小,输入平均间隔距离
func NewMyBox(p float32, objects ...fyne.CanvasObject) *fyne.Container {
return container.New(&myLayout{padding: p}, objects...)
}
// 自定义布局
// 注意:自定义水平布局,最大高度受外部容器影响,可能不生效
type myLayout struct {
padding float32 // 控件间隔
}
// 设置每个控件大小和位置
func (l *myLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
x := float32(0) // x坐标,控件距左边距离
for _, child := range objects { // 循环遍历所有控件
size = child.Size() // 获取当前控件的设置的大小(宽、高)
size.Height = child.Size().Height // 控件高度为控件的默认最小高度
size.Width = fyne.Max(size.Width, child.MinSize().Width) // 控件的最小宽度和实际宽度取最大值
child.Resize(size) // 设置控件大小
child.Move(fyne.NewPos(x, 0)) // 设置控件位置
x += size.Width + l.padding // 计算下一个控件位置
}
}
// 设置容器大小(宽,高)
func (l *myLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
size := fyne.NewSize(0, 0) // 初始化容器大小
for _, child := range objects { // 循环遍历每个控件
temp := fyne.NewSize(0, 0) // 临时存储获取的大小
minSize := child.MinSize() // 控件最小绘制大小
mSize := child.Size() // 控件设置大小
temp.Height = fyne.Max(minSize.Height, mSize.Height) // 获取当前控件默认高度和设置高度的最大值
size.Height = fyne.Max(size.Height, temp.Height) // 设置容器最大高度为最高控件的高度值
temp.Width = fyne.Max(minSize.Width, mSize.Width) // 获取当前控件默认宽度和设置宽度的最大值
size.Width += temp.Width + l.padding // 容器宽度 = 每个控件宽度 + 间距
}
return size // 返回容器大小
}
四、使用自定义容器
package main
import (
"fmt"
"fyne.io/fyne/v2" //go get fyne.io/fyne/v2@latest
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
"github.com/flopp/go-findfont" // go get github.com/flopp/go-findfont
"os"
"strconv"
"strings"
)
func init() {
//设置中文字体:解决fyne中文乱码问题
fontPaths := findfont.List() // 获取系统中所有的字体路径
for _, path := range fontPaths { // 判断字体是否在路径中
if strings.Contains(path, "msyh.ttf") || strings.Contains(path, "simhei.ttf") || strings.Contains(path, "simsun.ttc") || strings.Contains(path, "simkai.ttf") || strings.Contains(path, "STHeiti Medium.ttc") || strings.Contains(path, "Songti.ttc") {
os.Setenv("FYNE_FONT", path) // 系统中存在的字体路径,设置为应用的字体
break
}
}
}
func main() {
myApp := app.New() // 创建应用
w := myApp.NewWindow("计数") // 窗口标题
w.Resize(fyne.NewSize(800, 400)) // 窗口大小
w.CenterOnScreen() // 窗口屏幕居中显示
l1 := widget.NewLabel("设置计数:") // 文本标签1
l2 := widget.NewLabel("5") // 文本标签2,默认为5
b1 := widget.NewButton("+", func() { // 按钮+
v, _ := strconv.Atoi(l2.Text) // 字符串转整型
v++
if v > 15 { // 最大值为15
v = 15
}
l2.SetText(strconv.Itoa(v)) // 整型转字符串,赋值
})
b1.Resize(fyne.NewSize(b1.MinSize().Height, b1.MinSize().Height/3)) // 设置+按钮大小
b2 := widget.NewButton("-", func() {
v, _ := strconv.Atoi(l2.Text) // 字符串转整型
v--
if v < 1 { // 最小值为1
v = 1
}
l2.SetText(strconv.Itoa(v)) // 整型转字符串,赋值
})
b2.Resize(fyne.NewSize(b2.MinSize().Height, b2.MinSize().Height*5)) // 设置-按钮大小
w.SetContent(NewMyBox(5, l1, l2, b1, b2)) // 使用自定义容器,控件间距设置为5
w.ShowAndRun() // 显示窗口并运行应用
}
原文地址:https://blog.csdn.net/qq_30712797/article/details/145184986
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!