当前位置: 首页 > article >正文

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()                             // 显示窗口并运行应用
}

http://www.kler.cn/a/508378.html

相关文章:

  • PyBroker:利用 Python 和机器学习助力算法交易
  • 重拾Python学习,先从把python删除开始。。。
  • 算法(蓝桥杯)贪心算法7——过河的最短时间问题解析
  • 职场沟通与行为
  • C#-方法(函数)
  • 计算机组成原理(计算机系统3)--实验二:MIPS64乘法实现实验
  • sparkSQL练习
  • 使用FineBI进行数据分析(入门级)
  • 天机学堂3-ES+Caffeine
  • 多个页面一张SQL表,前端放入type类型
  • C++实现设计模式---中介者模式 (Mediator)
  • 【机器学习:三十三(一)、支持向量机】
  • YOLOv11改进,YOLOv11检测头融合RFAConv卷积,并添加小目标检测层(四头检测),适合目标检测、分割等任务
  • RV1126+FFMPEG推流项目(7)AI音频模块编码流程
  • 游戏引擎学习第80天
  • VTK知识学习(36)-图像平滑
  • 【spark源码修改】hive3.1.3 spark3.5.4编译,需要修改源码,最终编译成功
  • 全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之一维数组(应用技巧)
  • linux 国产化命令
  • 算法随笔_10: 供暖器
  • Linux网络 TCP socket
  • 一体机cell服务器更换内存步骤
  • java 小红书源码 1:1还原 uniapp
  • 小识MySQL中的OLTP和OLAP
  • 全类别机器人传感器模块推荐
  • RK3568笔记七十五:FFMPEG交叉编译