错误或功能:没有focusOwner如果控件直接添加到场景?

时间:2015-03-27 11:52:50

标签: java focus javafx-8

注意到一个以root显示“裸”控件的场景(在控件下面的示例中是TableView)最初没有focusOwner。事实上,根本没有focusOwner(场景的属性不会触发)。如果没有focusOwner,则无法通过键盘访问控件。承认,这不是一个非常现实的现实场景,但无论如何......

将控件添加到任何Parent,然后将该父控件设置为root将焦点转移到控件 - 这是我期望的。

出了什么问题 - 我的期望还是行为?

/**
 * Table doesn't have focus initially if not wrapped into a Parent.
 * jdk 8u60b5 (didn't try others)
 */
public class TableInitialCellEdit extends Application {

    ObservableList<MenuItem> data = FXCollections.observableArrayList(
            new MenuItem("some"),
            new MenuItem("dummy"),
            new MenuItem("data")
            );

    private Parent getContent() {
        TableView<MenuItem> table = new TableView<>(data);
        table.setEditable(true);
        TableColumn<MenuItem, String> text = new TableColumn<>("Text");
        text.setCellValueFactory(new PropertyValueFactory<>("text"));
        text.setCellFactory(TextFieldTableCell.forTableColumn());
        table.getColumns().addAll(text);
        // focus transfered to table if contained in a pane
        // return new Pane(table);
        // focus not transfered to table if contained directly in the scene 
        return table;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(getContent());
        scene.focusOwnerProperty().addListener((s, old, value) -> System.out.println(value));
        primaryStage.setScene(scene);
        primaryStage.setTitle(VersionInfo.getRuntimeVersion());
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

1 个答案:

答案 0 :(得分:1)

Node.requestFocus()的文档来看,我认为这种行为是个错误。

我的猜测是方法.com.sun.javafx.scene.traversal.TabOrderHelper#getFirstTargetNode(Parent)

中的错误
public static Node getFirstTargetNode(Parent p) {
    if (p == null || isDisabledOrInvisible(p)) return null;
    final ParentTraversalEngine impl_traversalEngine = p.getImpl_traversalEngine();
    if (impl_traversalEngine!= null && impl_traversalEngine.canTraverse()) {
        Node selected = impl_traversalEngine.selectFirst();
        if (selected != null) {
            return selected;
        }
    }
    List<Node> parentsNodes = p.getChildrenUnmodifiable();
    for (Node n : parentsNodes) {
        if (isDisabledOrInvisible(n)) continue;
        final ParentTraversalEngine parentEngine = n instanceof Parent ? ((Parent)n).getImpl_traversalEngine() : null;
        if (parentEngine != null ? parentEngine.isParentTraversable() : n.isFocusTraversable()) {
            return n;
        }
        if (n instanceof Parent) {
            Node result = getFirstTargetNode((Parent)n);
            if (result != null) return result;
        }
    }
    return null;
}

如果我正确读取它,它会递归p的层次结构以找到要聚焦的合适节点。在这种情况下,p是表。它通过其子级孩子进行递归但从未找到要关注的节点,直到它返回null。问题可能是,此方法从不考虑返回p本身。