概述
在写myList
类的时候,就想到可以写一个类似的Todo清单类。
基础思路
- 本质还是在内部维护一个数组,在其基础上进行增删改查操作的封装
- 为了方便存储数据,编写一个自定义内置类
TodoItem
,内部数组就变成了Array[TodoItem]
类型的类型化数组。在这个数组基础上编写各种方法。
基于本文所写的这个类实际上已经可以写简单的清单应用了。当然为了能用于打印输出,所以我也设定了以纯字符形式输出的方法。
代码
# ========================================================
# 名称:myTodoList
# 类型:类
# 简介:专用于构造待办清单列表的类
# 作者:巽星石
# Godot版本:v4.2.2.stable.official [15073afe3]
# 创建时间:2024年4月27日13:30:09
# 最后修改时间:2024年4月27日22:17:18
# ========================================================
class_name myTodoListvar _arr:Array[TodoItem] # 数据 - 内部维护的类型化数组# ============================= 常量与取值函数 ===========================
# 列表项状态
enum {UNCHECKED,CHECKED,CANCLE}var state_chars := "☐☑☒" # 状态字符# 获取对应常量的状态字符
func get_state_char(state:=UNCHECKED):return state_chars[state]
# ============================= 内部类 ===========================
# 清单列表项
class TodoItem:var status:int = UNCHECKED # 状态var content:String ="" # 内容func _init(ctn:String,state:int = UNCHECKED) -> void:content = ctnstatus = state
# ============================= 虚函数 ===========================
# 实例化
func _init(list:PackedStringArray = []) -> void:for itm in list:var item = TodoItem.new(itm)_arr.append(item)
# ============================= 方法 ===========================
# -------------------- 增删改查 --------------------
# -------------------- 增
# 添加清单项
func append(itm:String,state:int = UNCHECKED) -> void:var item = TodoItem.new(itm,state)_arr.append(item)# 添加多个清单项
func append_array(items:PackedStringArray,state:int = UNCHECKED) -> void:for i in range(items.size()):append(items[i],state)# 在指定位置添加清单项
func insert(pos:int,itm:String,state:int = UNCHECKED) -> void:var item = TodoItem.new(itm,state)_arr.insert(pos,item)
# -------------------- 删
# 移除列表项
func remove(idx:int) -> void:_arr.remove_at(idx)# 清空列表项
func clear() -> void:_arr.clear()
# -------------------- 改
# --------- 修改清单项的勾选状态 ---------
# 勾选列表项
func check(idx:int) -> void:_arr[idx].status = CHECKED# 勾选列表项
func uncheck(idx:int) -> void:_arr[idx].status = UNCHECKED# 勾选列表项
func cancle(idx:int) -> void:_arr[idx].status = CANCLE
# --------- 修改清单项的值和位置 ---------
# 修改列表项的值
func set_item(idx:int,new_val:String) -> void:_arr[idx].content = new_val# 修改列表项的位置
func move_to(idx:int,new_pos:int) -> void:var item = _arr[idx]_arr.remove_at(idx)_arr.insert(new_pos if new_pos !=0 else 0,item)
# -------------------- 查
# 获取列表项
func get_item(idx:int) ->TodoItem:return _arr[idx]# 返回列表项的总数
func get_count() ->int:return _arr.size()
# -------------------- 遍历
# 遍历函数
func for_item(callback:Callable) ->void:for i in range(_arr.size()):callback.callv([_arr[i],i,_arr.size()])
# -------------------- 获取清单 --------------------
# 返回清单列表
func get_data() -> Array[TodoItem]:return _arr.duplicate() # 返回副本# 返回清单列表
func _to_string() -> String:var strr = ""for i in range(_arr.size()):strr += "%s %s\n" % [get_state_char(_arr[i].status),_arr[i].content]return strr
基础原理
class_name myTodoListvar _arr:Array[TodoItem] # 数据 - 内部维护的类型化数组# ============================= 常量与取值函数 ===========================
# 列表项状态
enum {UNCHECKED,CHECKED,CANCLE}var state_chars := "☐☑☒" # 状态字符# 获取对应常量的状态字符
func get_state_char(state:=UNCHECKED):return state_chars[state]
# ============================= 内部类 ===========================
# 清单列表项
class TodoItem:var status:int = UNCHECKED # 状态var content:String ="" # 内容func _init(ctn:String,state:int = UNCHECKED) -> void:content = ctnstatus = state
观察最顶部的代码可以发现:
- 整个
myTodoList
内部维护一个名为_arr
的数组,它是Array[TodoItem]
的类型数组,只存储也只能存储TodoItem
类型的实例 TodoItem
是内部类,有2个基础属性status
和content
,分别存储清单项的状态(是否选中或取消),以及文本内容TodoItem
构造函数中默认的状态设置为UNCHECKED
也就是未选中TodoItem
的状态可以是UNCHECKED
,CHECKED
,CANCLE
其中之一,分别对应未选中、选中和取消state_chars
中存储了TodoItem
3种状态对应的字符组成的字符串☐☑☒
get_state_char()
用于获取UNCHECKED
,CHECKED
,CANCLE
对应的state_chars
中的字符,用于在get_todo_list_string()
中返回纯字符串的Todo清单。
基础使用
myTodoList
的方法和使用基本上与myList
类一致,也与GDScript的数组基本保持一致,所以上手没什么难度。除了设定状态的3个方法:
uncheck()
:将指定位置的项设为不勾选check()
:将指定位置的项设为勾选cancle()
:将指定位置的项设为取消
var list = myTodoList.new(["待办事项1","待办事项2","待办事项3"]) # 创建实例
list.check(0) # 选中第1项
list.cancle(1) # 取消第2项
list.append("待办事项4")
list.append("待办事项5",list.CHECKED)
list.append_array(["待办事项6","待办事项7","待办事项8"],list.CHECKED)
print(list.get_todo_list_string())
输出:
☑ 待办事项1
☒ 待办事项2
☐ 待办事项3
☐ 待办事项4
☑ 待办事项5
☑ 待办事项6
☑ 待办事项7
☑ 待办事项8
改进
使用_to_string()
_to_string()
虚函数是用于在类内部自定义to_string()
返回值的。在使用print()
或其他打印函数时,会自动调用to_string()
,打印其返回值。
我们将原来的get_todo_list_string()
方法改为_to_string()
。
# 返回清单列表
func _to_string() -> String:var strr = ""for i in range(_arr.size()):strr += "%s %s\n" % [get_state_char(_arr[i].status),_arr[i].content]return strr
则,在打印时,我们可以直接print()
我们创建的实例:
var list = myTodoList.new(["待办事项1","待办事项2","待办事项3"]) # 创建实例
print(list)
而如果我们想要字符串本身,可以使用list.to_string()
。