如何获取当前拥有焦点的控制节点?

How do I get which Control node currently has focus?

我正在尝试确定哪个 Control node has just changed focus. Another Control node has been set up for using focus by changing the focus mode on the node to All. From within that node's script, I can tell if it has focus by checking has_focus。但是,我想从另一个脚本判断它是否改变了焦点。

我知道有 focused_entered and focus_exited signals 我可以听,但是这些组件在组件树上彼此相距很远,我不想通过一堆连接或冒泡信号不相关的组件。

Control documentation says:

Only one Control node can be in keyboard focus.

既然只有一个节点处于焦点,是否有一个全局函数可以确定单个节点当前具有焦点的是什么?我如何判断全局焦点何时发生变化?

get_focus_owner 是一个全局函数,它将使节点处于焦点状态,如果有的话:

Returns the control that has the keyboard focus or null if none.

它可以通过几种方式在代码中使用:

每一帧

var focused_node
func _process(_delta):
    focused_node = get_focus_owner()
    
    if focused_node != null:
        # Runs every time a frame is drawn
        print(focused_node.name)

每次焦点变化

var focused_node
func _process(_delta):
    var new_focused_node = get_focus_owner()
    if new_focused_node != focused_node:
        focused_node = new_focused_node
        if(focused_node != null):
            # Runs every time the focused node changes
            print(focused_node.name)

某类节点的每次焦点变化

var focused_node
func _process(_delta):
    var new_focused_node = get_focus_owner()
    if new_focused_node != focused_node:
        focused_node = new_focused_node
        if(focused_node is Button):
            # Runs every time the focused node of a specific type changes
            print(focused_node.name)

Viewport 有一个 "gui_focus_changed" 信号可以用于此。它将为您提供每次更改时都具有焦点的控件。

您可以通过这样的代码连接到它:

func ready() -> void:
    get_viewport().connect("gui_focus_changed", self, "_on_focus_changed")

func _on_focus_changed(control:Control) -> void:
    if control != null:
        print(control.name)

顺便说一下,如果你看一下 get_focus_owner (here) 的源代码,代码中有 ControlViewport 是为焦点所有者。你需要场景树中的 Control 才能使用 get_focus_owner.

通过使用 "gui_focus_changed",您不必使用每帧运行的 _process。因此,您的使用量会减少 CPU。