键盘焦点
九个按钮通过 focus_neighbor 连成环形,用 tab 和方向键遍历。这是一套不用鼠标也能操作的界面。
上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。
用到的 Godot 类
ButtonGridContainer
代码
scripts/main.gd
extends Node
var status: Label
var first: Button
func _ready() -> void:
var column: VBoxContainer = _root()
var title: Label = Label.new()
title.text = 'Focus without a mouse'
title.add_theme_font_size_override('font_size', 26)
column.add_child(title)
var hint: Label = Label.new()
hint.text = 'tab walks the ring, arrows follow focus_neighbor and wrap at the edges, enter presses'
hint.add_theme_color_override('font_color', Color('#999999'))
column.add_child(hint)
var grid: GridContainer = GridContainer.new()
grid.columns = 3
grid.add_theme_constant_override('h_separation', 12)
grid.add_theme_constant_override('v_separation', 12)
column.add_child(grid)
var buttons: Array[Button] = []
for i in 9:
var button: Button = Button.new()
button.text = 'cell %d' % i
button.custom_minimum_size = Vector2(130, 60)
button.focus_entered.connect(func(): _say('focus on cell %d' % i))
button.pressed.connect(func(): _say('pressed cell %d' % i))
grid.add_child(button)
buttons.append(button)
# the modulo closes the grid into a ring, so leaving on the right enters on the left
for i in buttons.size():
buttons[i].focus_neighbor_left = buttons[(i + 8) % 9].get_path()
buttons[i].focus_neighbor_right = buttons[(i + 1) % 9].get_path()
buttons[i].focus_neighbor_top = buttons[(i + 6) % 9].get_path()
buttons[i].focus_neighbor_bottom = buttons[(i + 3) % 9].get_path()
status = Label.new()
status.add_theme_color_override('font_color', Color('#8eef97'))
column.add_child(status)
first = buttons[0]
first.grab_focus()
func _say(message: String) -> void:
status.text = message
func _root() -> VBoxContainer:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var center: CenterContainer = CenterContainer.new()
add_child(center)
center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 16)
center.add_child(column)
return column