自学内容网 自学内容网

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
}

三、我的自定义容器代码

  • 注意:自定义容器中控件宽、高,可能受自定义容器的外部容器影响,修改控件宽、高时,可能没有效果,需要对外部容器也要做相应操作。
  • 可以通过查看fynecontainer源码定义的布局,扩充自定义布局功能。

以下是我简易布局代码:

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)!