控件可见性

遇到的BUG

一开始我使用的是一个封装好的切换函数(由于写博客的时候我已经删掉了原代码,这里没有贴上代码),每次我点击时,就对可见性进行反转……不过之后的测试中我遇到了一个BUG,当我先点击continue再点击start时,可见性关系会彻底错乱:

简单来说,由于我点击了continue,使得continuemenu可见、setting、end不可见,此时再点击start进行反转,就会变成setting、end可见……一团乱。

之后我仔细思考了一下解决办法,决定加上一个记录点击次数的功能。

但途中,我发现如果按照之前的操作那样点击,也就是continue -> start,可见性倒是没乱了,可由于点击次数加了1,而第二次点击时的效果就会变成恢复可见性……这就导致需要点两次才能弹出菜单。

我最后的解决办法是:给三个菜单的点击次数都分别加上了点击次数的统计,并且在他们点击的时候清除另外两个按钮的点击次数,这样就不会导致需要点击两次才能弹出来的情况了。

不过代码方面就……朴实无华。

func _ready():
# 初始可见性
$ScrollContainer/VBoxContainer/Start.visible = true
$ScrollContainer/VBoxContainer/StartMenu.visible = false
$ScrollContainer/VBoxContainer/Continue.visible = true
$ScrollContainer/VBoxContainer/ContinueMenu.visible = false
$ScrollContainer/VBoxContainer/Setting.visible = true
$ScrollContainer/VBoxContainer/SettingMenu.visible = false
$ScrollContainer/VBoxContainer/End.visible = true

# 点击控件的可见性切换
var click_counts = [0, 0, 0]
func _on_start_pressed(): toggle_visibility(0)
func _on_continue_pressed(): toggle_visibility(1)
func _on_setting_pressed(): toggle_visibility(2)

func toggle_visibility(button_index):
	for i in range(3):
		if i == button_index:
			click_counts[i] += 1
			if click_counts[i] % 2 == 0:
				$ScrollContainer/VBoxContainer/End.visible = true
				$ScrollContainer/VBoxContainer/Setting.visible = true
				$ScrollContainer/VBoxContainer/Continue.visible = true
				$ScrollContainer/VBoxContainer/StartMenu.visible = false
				$ScrollContainer/VBoxContainer/SettingMenu.visible = false
				$ScrollContainer/VBoxContainer/ContinueMenu.visible = false
			else:
				if i == 0:
					$ScrollContainer/VBoxContainer/StartMenu.visible = true
					$ScrollContainer/VBoxContainer/Continue.visible = false
					$ScrollContainer/VBoxContainer/ContinueMenu.visible = false
					$ScrollContainer/VBoxContainer/Setting.visible = false
					$ScrollContainer/VBoxContainer/SettingMenu.visible = false
					$ScrollContainer/VBoxContainer/End.visible = false
				elif i == 1:
					$ScrollContainer/VBoxContainer/StartMenu.visible = false
					$ScrollContainer/VBoxContainer/Continue.visible = true
					$ScrollContainer/VBoxContainer/ContinueMenu.visible = true
					$ScrollContainer/VBoxContainer/Setting.visible = false
					$ScrollContainer/VBoxContainer/SettingMenu.visible = false
					$ScrollContainer/VBoxContainer/End.visible = false
				elif i == 2:
					$ScrollContainer/VBoxContainer/StartMenu.visible = false
					$ScrollContainer/VBoxContainer/Continue.visible = true
					$ScrollContainer/VBoxContainer/ContinueMenu.visible = false
					$ScrollContainer/VBoxContainer/Setting.visible = true
					$ScrollContainer/VBoxContainer/SettingMenu.visible = true
					$ScrollContainer/VBoxContainer/End.visible = false
		else:
			click_counts[i] = 0

精简代码

如你所见,代码倒是挺直观的,就是太长了,有很多冗余部分。所以我的下一步是,精简代码。

以下是我精简后的代码,我使用了一个新的函数 set_visibility 来接受 true or false,这样也能够把初始可见性和点击可见性合并到了一起。

func _ready():
	# 初始可见性
	set_visibility(true, false, true, false, true, false, true)

# 点击按钮的可见性切换
var click_counts = [0, 0, 0]

func _on_start_pressed(): toggle_visibility(0)
func _on_continue_pressed(): toggle_visibility(1)
func _on_setting_pressed(): toggle_visibility(2)

func toggle_visibility(button_index):
	# 清空其他按钮的点击次数
	for i in range(click_counts.size()):
		click_counts[i] = 0 if i != button_index else click_counts[i] + 1
	
	var is_visible = click_counts[button_index] % 2 == 0
	print("按钮 %d 点击次数: %d,可见性: %s" % [button_index, click_counts[button_index], is_visible])
	match button_index:
		0:
			set_visibility(true, not is_visible, is_visible, false, is_visible, false, is_visible)
		1:
			set_visibility(true, false, true, not is_visible, is_visible, false, is_visible)
		2:
			set_visibility(true, false, true, false, true, not is_visible, is_visible)

func set_visibility(start, start_menu, continue_, continue_menu, setting, setting_menu, end):
	$ScrollContainer/VBoxContainer/Start.visible = start
	$ScrollContainer/VBoxContainer/StartMenu.visible = start_menu
	$ScrollContainer/VBoxContainer/Continue.visible = continue_
	$ScrollContainer/VBoxContainer/ContinueMenu.visible = continue_menu
	$ScrollContainer/VBoxContainer/Setting.visible = setting
	$ScrollContainer/VBoxContainer/SettingMenu.visible = setting_menu
	$ScrollContainer/VBoxContainer/End.visible = end

代码到这里就差不多完成了,不过我个人比较喜欢钻牛角尖,match的性能消耗稍微高了那么一点点,也不够好看,换成数组的方式更加直观高效。

下面这个代码中,visibilities[button_index]中的button_index代表我们点击的是第几个控件,这是前面定义好的,同时这也会作为一个索引值,返回数组中对应行的值。不过记得,改成这样的话,前面的初始化也得改成数组的形式。

# 点击按钮的可见性切换

......(未修改部分就省略了)

	var visibilities = [
		[true, not is_visible, is_visible, false, is_visible, false, is_visible],
		[true, false, true, not is_visible, is_visible, false, is_visible],
		[true, false, true, false, true, not is_visible, is_visible]
	]
	
	set_visibility(visibilities[button_index])

func set_visibility(visibility_array):
	$ScrollContainer/VBoxContainer/Start.visible = visibility_array[0]
	$ScrollContainer/VBoxContainer/StartMenu.visible = visibility_array[1]
	$ScrollContainer/VBoxContainer/Continue.visible = visibility_array[2]
	$ScrollContainer/VBoxContainer/ContinueMenu.visible = visibility_array[3]
	$ScrollContainer/VBoxContainer/Setting.visible = visibility_array[4]
	$ScrollContainer/VBoxContainer/SettingMenu.visible = visibility_array[5]
	$ScrollContainer/VBoxContainer/End.visible = visibility_array[6]
本文作者:晝行燈

版权声明:本文采用 CC BY-NC 4.0 协议授权

转载需注明作者及原文链接: https://mansifield.pages.dev/80yb08/