【Godot4.2】文件系统自定义控件 - GroupButtons

news2024/9/23 9:21:19

GroupButtons

概述

读者朋友们好,我是巽星石,这是我的Godot4.2文件系统自定义控件系列文章。

在很多程序或插件设计中,都会用到一堆按钮的形式,好处是比较直观,用啥点啥,本质上相当于一个简化的二级树形导航结构。

这种结构我在自己编写的Godot插件myAdd中使用过,这次是基于Godot4.2重新编写,并通过解析自定义数据形式简化使用的版本。

在这里插入图片描述

代码

同样只需要拷贝下面的代码到你的插件或程序项目(Godot4.2或以上)中,可以命名为“GroupButtons.gd”。

# =============================================
# 名称:GroupButtons
# 类型:自定义节点(扩展控件)
# 描述:专用于显示分组按钮
# 作者:巽星石
# Godot版本:v4.2.1.stable.official [b09f793f5]
# 创建时间:20242723:59:18
# 最后修改时间:20242801: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 = val
		reload()

## 展开图标,显示在分组按钮右侧
@export var expand_icon:Texture2D:
	set(val):
		expand_icon = val
		reload()

## 收起图标,显示在分组按钮右侧
@export var fold_icon:Texture2D:
	set(val):
		fold_icon = val
		reload()

var root:VBoxContainer  # 添加分组的VBox容器

# 实例化时进行初始化构建
func _init():
	# 创建最基础的容器框架
	var scroll = ScrollContainer.new()
	var vbox = VBoxContainer.new()
	vbox.size_flags_horizontal=Control.SIZE_EXPAND_FILL
	scroll.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_data
	var 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 = title
	return btn

# 创建并返回一个分组标题按钮实例
func group_button(gup_name:String) -> Button:
	var gup_btn = button(gup_name)
	gup_btn.icon = fold_icon
	gup_btn.expand_icon = true
	gup_btn.icon_alignment=HORIZONTAL_ALIGNMENT_RIGHT
	gup_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.visible
				if gup_btn.icon == fold_icon:
					gup_btn.icon = expand_icon
				else:
					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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1440653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器:记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库:git init(base) [rootlocalhost gitcode]# gi…

【通讯录案例-偏好设置 Objective-C语言】

一、刚才,我们plist存储,讲完了,这个plist,我直接,右键,打开 打开 不用xcode,我就用文本文档打开,打开方式:其他 选择:文本编辑 打开 好,这个里边儿啊,就是我们刚才存的一个Key:Value 它本质上,是一个xml 这是一种文件的格式, 等你们讲到网络的时候,实际上,…

Android 环境搭建

1、桥接工具安装 网站地址:AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 使用安装包: adb 查看当前链接成功的设备:adb devices 使用adb shell指令来进入到手机的后台:

Ondo宣布将其原生稳定币USDY带入Sui生态

重要提示:USDY是由短期美国国债支持的token化票据,持有者享受稳定币的实用性同时获得收益。USDY不得在美国或向美国人出售或以其他方式提供。USDY也未根据1933年美国证券法注册。 不到一年的时间,Sui已经成为全链TVL排名前十的区块链&#xf…

MySQL- 运维-分库分表-Mycat

一、Mycat概述 1、安装 2、概念介绍 二、Mycat入门 启动服务 三、Mycat配置 1、schema.xml 2、rule.xml 3、server.xml 四、Mycat分片 1、垂直分库 2、水平分表 五、Mycat管理及监控 1、Mycat原理 2、Mycat管理工具 (1)、命令行 (2&#…

SpringBoot + Tess4J 实现本地与远程图片的文字识别

1 前言 1.1 概要 在本文中,我们将探讨如何在Spring Boot应用程序里集成Tess4J来实现OCR(光学字符识别),以识别出本地和远程图片中的文字。 我们将从添加依赖说起,然后创建服务类以实现OCR,最后展示如何处…

基于微信小程序的新生报到系统的研究与实现,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

如何给闲置电脑安装黑群晖

准备 diskgenius ,黑群晖引导文件(有些需要扩展驱动包),如果给U盘安装需要balenaEtcher或者rufus(U盘安装还需要ChipGenus),如果给硬盘安装需要有pe推荐firePE或U启通 我以U盘为例 首先去找这…

【RPA】浅谈RPA技术及其应用

摘要:随着信息技术的飞速发展,企业对于自动化、智能化的需求日益增强。RPA(Robotic Process Automation,机器人流程自动化)技术应运而生,为企业提供了全新的自动化解决方案。本文首先介绍了RPA技术的基本概…

Stability AI一种新型随心所欲生成不同音调、口音、语气的文本到语音(TTS)音频模型

该模型无需提前录制人声样本作为参考,仅凭文字描述就能生成所需的声音特征。用户只需描述他们想要的声音特点,例如“一个语速较快、带有英国口音的女声”,模型即可相应地生成符合要求的语音。它不仅能模仿已有的声音,还能根据用户…

ESP8266 tcpsocket透传模式流程介绍

一、整体流程介绍 二、固件介绍 固件视频演示地址: ESP8266-配网&热点设置说明_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1hq4y127dN/?spm_id_from333.999.0.0

第三百一十五回

文章目录 1. 概念介绍2. 基本用法3. 补充用法4. 内容总结 我们在上一章回中介绍了"再谈ListView中的分隔线",本章回中将介绍showMenu的用法.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在第一百六十三回中介绍了showMenu相关的内容…

Log4j2漏洞(二)3种方式复现反弹shell

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与学习之用,读者将信息做其他用途,由Ta承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 1、前言 明天就是除夕了,提前祝大家&#x…

Apollo

一. 部署说明 apollo配置中心由三个组件组成: ConfigService 配置中心,客户端从这个服务拉配置,同时内置了Eureka、MetaService。每个环境要有一个 AdminService 配置管理服务,管理数据库配置,Portal调这个服务修改、…

解决端口被占用问题

写文章原因: 本人在安装alist的时候,在使用5244端口的时候,显示端口被占用,于是想查看一下端口是被什么程序占用了,是否可以杀死占用的程序,还是更换端口. failed to start http: listen tcp 0.0.0.0:5244: bind: Only one usage of each socket address (protocol/network a…

专业140+总分420+华中科技大学824信号与系统考研经验电子信息与通信工程,真题,大纲,参考书。

今年考研分数自己感觉还是比较满意,专业824信号与系统考的最好140,总分420,如愿上岸华科,回顾自己的这一年的复习,总结一些自己的经验,希望对报考华科的同学有帮助。 专业课: 824信号与系统在…

如何构建一个高效的微服务治理闭环管理体系

随着企业业务的快速发展和数字化转型的推进,微服务架构因其高度的灵活性、可扩展性和可维护性而逐渐成为主流。然而,微服务架构的复杂性也带来了诸多治理挑战。为了有效应对这些挑战,构建一个微服务治理闭环至关重要。 1、微服务治理概述 微…

SpringCloud-Ribbon:负载均衡(基于客户端)

6. Ribbon:负载均衡(基于客户端) 6.1 负载均衡以及Ribbon Ribbon是什么? Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具。简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负…

C++面试宝典第27题:完全平方数之和

题目 给定正整数 n,找到若干个完全平方数(比如:1、4、9、16、...),使得它们的和等于n。你需要让组成和的完全平方数的个数最少。 示例1: 输入:n = 12 输出:3 解释:12 = 4 + 4 + 4。 示例2: 输入:n = 13 输出:2 解释:13 = 4 + 9。 解析 这道题主要考察应聘者对于…

Android中的MVVM

演变 开发常用的框架包括MVC、MVP和本文的MVVM,三种框架都是为了分离ui界面和处理逻辑而出现的框架模式。mvp、mvvm都由mvc演化而来,他们不属于某种语言的框架,当存在ui页面和逻辑代码时,我们就可以使用这三种模式。 model和vie…