RequestFocus in TextField doesn't work

2019-03-24 14:25发布

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 control.

4条回答
不美不萌又怎样
2楼-- · 2019-03-24 15:05

The exact same answer as @Sergey Grinev. Make sure your version of java is up-to-date (JDK 1.8 or later).

Platform.runLater(()->myTextField.requestFocus());
查看更多
做自己的国王
3楼-- · 2019-03-24 15:17

If you requestFocus(); AFTER initializing the scene, it will work!

Like this:

Stage stage = new Stage();
GridPane grid = new GridPane();
//... add buttons&stuff to pane

Scene scene = new Scene(grid, 800, 600);

TEXTFIELD.requestFocus();

stage.setScene(scene);
stage.show();

I hope this helps. :)

查看更多
Evening l夕情丶
4楼-- · 2019-03-24 15:19

At the time of initialize() controls are not yet ready to handle focus.

You can try next trick:

@Override
public void initialize(URL url, ResourceBundle rb) {
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            tf.requestFocus();
        }
    });
}

For tricky complex applications (like Pavel_K has in the comments) you may want to repeat this routine several times and call method line next one:

private void repeatFocus(Node node) {
    Platform.runLater(() -> {
        if (!node.isFocused()) {
            node.requestFocus();
            repeatFocus(node);
        }
    });
}

Note this is undocumented approach and it may be wise to add a limit for repetitions to avoid endless loop if something changed or broke in future Java releases. Better to lose focus than a whole app. :)

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-03-24 15:24

This can occur when the Scene property for the Node is not yet set. Alas, the scene property can take a "long" time to be set.

The child node's scene property lags when a scene is first created, and also, when items are added to some parents, such as a TabPane (oddly some parents seem immune, I'm not sure why).

The correct strategy, which has always worked for me :

if (myNode.scene) == null {
    // listen for the changes to the node's scene property,
    // and request focus when it is set
} else {
    myNode.requestFocus()
}

I have a handy Kotlin extension function which does this.

fun Node.requestFocusOnSceneAvailable() {
    if (scene == null) {
        val listener = object : ChangeListener<Scene> {
            override fun changed(observable: ObservableValue<out Scene>?, oldValue: Scene?, newValue: Scene?) {
                if (newValue != null) {
                    sceneProperty().removeListener(this)
                    requestFocus()
                }
            }
        }
        sceneProperty().addListener(listener)
    } else {
        requestFocus()
    }
}

You can then call it from within you code like so :

myNode.requestFocusOnSceneAvailable()

Perhaps somebody would like to translate it to Java.

查看更多
登录 后发表回答