在JavaFX中,我如何确定获得焦点的节点是否是我自己的子节点?

use*_*075 3 javafx

我正在使用JavaFX中的TableView.我想做的是跟踪对表格的编辑.当用户离开表格时,我想检查是否有任何编辑,如果是,则提示用户询问是否要保存更改.

我有TableView工作,我可以跟踪编辑,我可以确定TableView何时失去焦点(使用focusedProperty更改侦听器).

但问题是,当单击一个单元格进行编辑时,表格的focusedProperty更改侦听器将触发(编辑单元格获得焦点,表格本身会丢失它).我真正想要的是一种方法来判断焦点更改时是否更改为表的子节点(例如列或单元格)或表外的某些内容(在父GUI上选择不同的选项卡).但我不想将侦听器添加到可以单击的每个其他可能节点.

如果我知道如何获得当前关注的项目(还没有看到如何做到这一点),我可以递归调用getParent()并检查TableView是否在该列表中,如果是,我知道它是一个孩子.但我还没有看到一种通用的方法来获取应用程序中当前关注的节点.

迭代表的子节点没有好的通用方法,因为getChildrenUnmodifiable()返回我的Node()类型(我想我可以逐个转换以确定它们是否每个都有更多的子节点),或者我必须转到TableColumns然后来自那里的细胞(并检查每个细胞的图形).

我可能会以递归方式迭代子项,根据需要进行转换,并在此时检查isFocused(),除非有更好的解决方案.但是我希望这里的某个人可以更好地解决这个问题,最好是更通用的解决方案.

use*_*075 6

我从一个节点开始搜索,投射到子节点并检查焦点节点是否是一个孩子.它不优雅 - 当然感觉应该有更好的方式.但这是我过去常用的方法:

private boolean isChildFocused(javafx.scene.Parent parent)
{
    for (Node node : parent.getChildrenUnmodifiable())
    {
        if (node.isFocused())
        {
            return true;
        }
        else if (node instanceof javafx.scene.Parent)
        {
            if (isChildFocused((javafx.scene.Parent)node))
            {
                return true;
            }
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常(至少使用TableView作为根级父级),当父级的focusedProperty()更改为false(通过属性更改侦听器)时调用此方法.


小智 5

您可以通过场景的getFocusOwner()或focusOwnerProperty()获取当前聚焦的节点.正如您所说,从焦点节点到TableView的遍历更好.

    public void createTable() {
        TableView tableView = new TableView();
        tableView.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            if (oldValue && !newValue) {
                if (!isParent(tableView, tableView.getScene().getFocusOwner())) {
                    System.out.println("Saving changes.");
                }
            }
        });
    }

    public boolean isParent(Parent parent, Node child) {
        if (child == null) {
            return false;
        }
        Parent curr = child.getParent();
        while (curr != null) {
            if (curr == parent) {
                return true;
            }
            curr = curr.getParent();
        }
        return false;
    }
Run Code Online (Sandbox Code Playgroud)