RequestFocus in TextField doesn't work

后端 未结 6 724
猫巷女王i
猫巷女王i 2021-02-13 01:49

I use JavaFX 2.1 and I created GUI using FXML, in the controller of this GUI I added myTextField.requestFocus();.

But I always get the focus in the other co

6条回答
  •  北荒
    北荒 (楼主)
    2021-02-13 02:23

    The older answers account for the case of Platform.runLater not working, but this answer covers also the case of multiple requests on multiple nodes.

    Problem is: the order in which the scene property becomes non-null for the nodes, and thence the order in which the added listeners get called, is not necessarily the same as the order in which the two listeners were added. And so this order:

    requestFocusOnSceneAvailable(node1)
    requestFocusOnSceneAvailable(node2)
    

    might unexpectedly result in this order:

    node2.requestFocus()
    node1.requestFocus()
    

    A solution requires having the listeners call requestFocus() only on the most recent node, which can be tracked with a static variable:

    private static Node nodeToRequestFocusOnOnceSceneAvailable;
    
    public static void requestFocusOnceSceneAvailable(Node node) {
        
        // Remember this node as the latest node requested to receive focus.
        nodeToRequestFocusOnOnceSceneAvailable = node;
        
        // Schedule the focus request to happen whenever
        // JavaFX finally adds the node to the scene.
        Listeners.addAndFire(node.sceneProperty(), new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Scene oldScene, Scene newScene) {
                if (newScene != null) {
                    if (node == nodeToRequestFocusOnOnceSceneAvailable) {
                        node.requestFocus();
                        
                        // We no longer need to remember this node,
                        // since its focus has been requested.
                        nodeToRequestFocusOnOnceSceneAvailable = null;
                    }
                    
                    // We no longer need the listener
                    // after it has run once.
                    observable.removeListener(this);
                }
            }
        });
    }
    

    Note, this solution assumes there is only one scene.

提交回复
热议问题