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

9
我试图确定哪个 Control 节点刚刚改变了焦点。另一个 Control 节点已经设置为使用聚焦,通过将节点的焦点模式更改为 All。从该节点的脚本中,我可以通过检查 has_focus 来确定它是否具有焦点。但是,我想从另一个脚本中知道它是否已经改变了焦点。
我知道有 focused_enteredfocus_exited 信号,我可以监听这些信号,但是这些组件在组件树上相距很远,而且我不想通过一堆不相关的组件连接或向上冒泡信号。 Control 文档 中说:

只有一个 Control 节点可以具有键盘焦点。

由于只有一个节点处于聚焦状态,是否有一个全局函数可以确定当前具有焦点的单个节点?我如何知道全局焦点已更改?
2个回答

8
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 的源代码 (这里),代码要求Control询问所在的Viewport以获取其焦点所有者。因此,您需要在场景树中添加一个Control才能使用get_focus_owner
通过使用"gui_focus_changed",您不必使用每帧都会运行的_process。因此,您可以减少CPU使用率。

3

get_focus_owner是一个全局函数,如果有任何节点处于焦点状态,则会获取该节点:

返回具有键盘焦点的控件,如果没有则返回null。

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

每一帧

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接