Control.grab_focus
2026/4/14大约 4 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — Control.grab_focus
Control.grab_focus
定义
Control.grab_focus 就是让一个 UI 控件"获得焦点"——可以理解为"选中"它。被选中的控件会获得特殊的视觉提示(比如按钮周围的虚线框、文本框里的光标),并且可以接收键盘输入。
打个比方:想象你面前有一排按钮,grab_focus 就像用手指点了一下某个按钮,让它变成"当前活动"的那个。之后按键盘上的回车键就能直接触发这个按钮,按 Tab 键可以在按钮之间切换。
在实际游戏开发中,你经常需要让某个控件自动获得焦点:比如打开设置菜单时,第一个选项自动被选中;弹出输入框时,光标自动在里面闪烁,玩家不用再点击一下就能开始打字。
函数签名
C#
public void GrabFocus()GDScript
func grab_focus() -> void参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 无 | — | — | 此方法没有参数 |
返回值
无返回值(void)。调用后控件立即获得焦点。
代码示例
基础用法:让按钮获得焦点
C#
var startButton = GetNode<Button>("StartButton");
startButton.GrabFocus();
// 运行结果: StartButton 获得焦点,出现高亮边框,按回车可触发点击
var nameInput = GetNode<LineEdit>("NameInput");
nameInput.GrabFocus();
// 运行结果: NameInput 获得焦点,出现文字光标,可以直接输入文字GDScript
var start_button = $StartButton as Button
start_button.grab_focus()
# 运行结果: StartButton 获得焦点,出现高亮边框,按回车可触发点击
var name_input = $NameInput as LineEdit
name_input.grab_focus()
# 运行结果: NameInput 获得焦点,出现文字光标,可以直接输入文字实际场景:打开菜单时自动选中第一个按钮
C#
using Godot;
public partial class PauseMenu : Control
{
private Button _resumeButton;
public override void _Ready()
{
_resumeButton = GetNode<Button>("VBox/ResumeButton");
// 菜单打开时让"继续游戏"按钮自动获得焦点
_resumeButton.GrabFocus();
// 运行结果: 打开暂停菜单后,"继续游戏"按钮被高亮,玩家直接按回车就能继续
}
public override void _Input(InputEvent evt)
{
if (Input.IsActionJustPressed("ui_cancel"))
{
Visible = !Visible;
if (Visible)
{
_resumeButton.GrabFocus();
GetTree().Paused = true;
}
else
{
GetTree().Paused = false;
}
}
}
}GDScript
extends Control
@onready var _resume_button: Button = $VBox/ResumeButton
func _ready():
# 菜单打开时让"继续游戏"按钮自动获得焦点
_resume_button.grab_focus()
# 运行结果: 打开暂停菜单后,"继续游戏"按钮被高亮
func _input(evt):
if Input.is_action_just_pressed("ui_cancel"):
visible = not visible
if visible:
_resume_button.grab_focus()
get_tree().paused = true
else:
get_tree().paused = false进阶用法:自定义焦点链路(Tab 键导航顺序)
C#
using Godot;
public partial class LoginScreen : Control
{
private LineEdit _usernameInput;
private LineEdit _passwordInput;
private Button _loginButton;
public override void _Ready()
{
_usernameInput = GetNode<LineEdit>("UsernameInput");
_passwordInput = GetNode<LineEdit>("PasswordInput");
_loginButton = GetNode<Button>("LoginButton");
// 设置 Tab 键焦点切换顺序
_usernameInput.FocusNext = _passwordInput.GetPath();
_usernameInput.FocusPrevious = _loginButton.GetPath();
_passwordInput.FocusNext = _loginButton.GetPath();
_passwordInput.FocusPrevious = _usernameInput.GetPath();
_loginButton.FocusNext = _usernameInput.GetPath();
_loginButton.FocusPrevious = _passwordInput.GetPath();
// 页面打开后用户名输入框自动获得焦点
_usernameInput.GrabFocus();
// 运行结果: 打开登录页面后光标在用户名框,按 Tab 依次跳到密码框和登录按钮
}
public void OnLoginButtonPressed()
{
GD.Print($"登录:{_usernameInput.Text}");
// 运行结果: 点击登录按钮后打印输入的用户名
}
}GDScript
extends Control
@onready var _username_input: LineEdit = $UsernameInput
@onready var _password_input: LineEdit = $PasswordInput
@onready var _login_button: Button = $LoginButton
func _ready():
# 设置 Tab 键焦点切换顺序
_username_input.focus_next = _password_input.get_path()
_username_input.focus_previous = _login_button.get_path()
_password_input.focus_next = _login_button.get_path()
_password_input.focus_previous = _username_input.get_path()
_login_button.focus_next = _username_input.get_path()
_login_button.focus_previous = _password_input.get_path()
# 页面打开后用户名输入框自动获得焦点
_username_input.grab_focus()
# 运行结果: 打开登录页面后光标在用户名框,按 Tab 依次跳转
func on_login_button_pressed():
print("登录:%s" % _username_input.text)
# 运行结果: 点击登录按钮后打印输入的用户名注意事项
- 同一时间只有一个控件能获得焦点:当 A 获得焦点时,之前拥有焦点的 B 会自动失去焦点。
FocusMode决定控件能否获得焦点:默认情况下很多控件的FocusMode是FocusMode.All(可以通过点击或 Tab 获得焦点)。如果设为FocusMode.None,调用GrabFocus()无效。grab_focus()不能在_Ready()之前调用:如果控件还没进入场景树,调用会失败。可以在_Ready()中调用,或者使用CallDeferred("GrabFocus")延迟调用。grab_click_focus()的区别:还有一个GrabClickFocus()方法,它让控件在下次点击时获得焦点(而不是立即获得)。
