GroupButtons
概述
读者朋友们好,我是巽星石,这是我的Godot4.2文件系统自定义控件系列文章。
在很多程序或插件设计中,都会用到一堆按钮的形式,好处是比较直观,用啥点啥,本质上相当于一个简化的二级树形导航结构。
这种结构我在自己编写的Godot插件myAdd中使用过,这次是基于Godot4.2重新编写,并通过解析自定义数据形式简化使用的版本。
代码
同样只需要拷贝下面的代码到你的插件或程序项目(Godot4.2或以上)中,可以命名为“GroupButtons.gd”。
# =============================================
# 名称:GroupButtons
# 类型:自定义节点(扩展控件)
# 描述:专用于显示分组按钮
# 作者:巽星石
# Godot版本:v4.2.1.stable.official [b09f793f5]
# 创建时间:2024年2月7日23:59:18
# 最后修改时间:2024年2月8日01:30:44
# =============================================
@tool
extends PanelContainer
class_name GroupButtons## 按钮点击时触发
signal button_clicked(group_title:String,title:String)## 包含分组和具体按钮文本的自定义数据,格式如下:[br]
## 分组标题==按钮名称||按钮名称...[br]
## 分组标题==按钮名称||按钮名称...[br]
## ...
@export_multiline var data:String = "":set(val):data = valreload()## 展开图标,显示在分组按钮右侧
@export var expand_icon:Texture2D:set(val):expand_icon = valreload()## 收起图标,显示在分组按钮右侧
@export var fold_icon:Texture2D:set(val):fold_icon = valreload()var root:VBoxContainer # 添加分组的VBox容器# 实例化时进行初始化构建
func _init():# 创建最基础的容器框架var scroll = ScrollContainer.new()var vbox = VBoxContainer.new()vbox.size_flags_horizontal=Control.SIZE_EXPAND_FILLscroll.add_child(vbox)add_child(scroll)root = vbox# 根据data重新加载整个分组按钮列表
func reload():# 清空原有分组for child in root.get_children():child.queue_free()# 加载新分组var datas = data.split("\n")for dt in datas:add_group(dt)# 根据分组数据(形如“分组标题==按钮名称||按钮名称”)添加一个分组
func add_group(gup_data:String):var gup_name = gup_datavar datas = gup_data.split("==")if datas.size()>0:gup_name = datas[0]# 创建分组和分组标题按钮var vbox = vbox(group_button(gup_name))var grid = grid()grid.columns = 2# 创建具体的按钮if datas.size()>1:var btns = datas[1].split("||")for bt in btns:var btn = button(bt)btn.size_flags_horizontal=Control.SIZE_EXPAND_FILL## 按钮点击处理btn.connect("pressed",func():emit_signal("button_clicked",gup_name,bt))grid.add_child(btn)vbox.add_child(grid)root.add_child(vbox)# ============================ 控件生成函数 ============================
# ============== 说明:以下函数仅用于生成控件或容器,用于简化代码
# 创建并返回一个VBoxContainer实例,并添加child为子节点
func vbox(child:Control = null) -> VBoxContainer:var v_box = VBoxContainer.new()if child:v_box.add_child(child)return v_box# 创建并返回一个GridContainer实例,并添加child为子节点
func grid(child:Control = null) -> GridContainer:var g = GridContainer.new()if child:g.add_child(child)return g# 创建并返回一个按钮实例
func button(title:String) -> Button:var btn = Button.new()btn.text = titlereturn btn# 创建并返回一个分组标题按钮实例
func group_button(gup_name:String) -> Button:var gup_btn = button(gup_name)gup_btn.icon = fold_icongup_btn.expand_icon = truegup_btn.icon_alignment=HORIZONTAL_ALIGNMENT_RIGHTgup_btn.flat = true# 分组按钮点击处理gup_btn.connect("pressed",func():var parent = gup_btn.get_parent()if parent is VBoxContainer:var grid = parent.get_child(1)if grid is GridContainer:grid.visible = not grid.visibleif gup_btn.icon == fold_icon:gup_btn.icon = expand_iconelse:gup_btn.icon = fold_icon)return gup_btn
使用方法
脚本拷贝和创建到项目中后,在具体场景中添加节点。
将控件放大至合适大小,在检视器面板设定参数,其中data属性采用的是我自定义的一种数据形式,格式如下:
分组标题==按钮名称||按钮名称...
分组标题==按钮名称||按钮名称...
...
也就是说:
- 每一行描述一个分组
==
之前是分组标题,之后==
之后是分组下的按钮标题,每个按钮标题之间用||
作为分隔
expand_icon和fold_icon用于在分组折叠或展开时显示。
因为本质上GroupButtons是基于PanelContainer,因此你可以用自定义的StyleBox资源修饰它。
通过自定义背景颜色,就可以获得更好的样式:
以下是调整后的样式:
但是在制作编辑器插件时,我更倾向于不去调整原始的控件和容器样式,因为一切都可以直接跟随编辑器的样式发生变化。
获取按钮点击信息
通过连接和处理自定义信号button_clicked
,可以获取每个按钮的分组标题及其自身的标题,通过match
之类的分支结构,可以进行具体的处理。
信号处理代码如下:
func _on_group_button_button_clicked(group_title, title):print(group_title,":",title)pass