Forum Stats

  • 3,855,322 Users
  • 2,264,499 Discussions
  • 7,905,968 Comments

Discussions

requestFocus for TextField

Muzib
Muzib Member Posts: 10
edited May 8, 2017 11:40AM in JavaFX 2.0 and Later

I know that a node's requestFocus() method doesn't work until -

  • it is visible,
  • disableProperty() is set to false, and
  • a scene owns it

but, if it is like this:

    TextField tf = new TextField(), tf2 = new TextField(), tf3 = new TextField();
    VBox holder = new VBox(5, tf, tf2, tf3);
    TitledPane tp = new TitledPane("Testing",holder);
    AnchorPane root = new AnchorPane(tp);

    @Override
    public void start(Stage primaryStage) {
        tp.setExpanded(false);
        tp.expandedProperty().addListener((c,o,n)->{
            if(n)
                tf.requestFocus();
        });
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }    public static void main(String[] args) {
        launch(args);
    }

then, all of the above is fulfilled but, still, textfield doesn't get focus if I expand the TitledPane.

Also, this doesn't seem to work:

Platform.runlater(()->tf.requestFocus());

Could anybody help me?

Tagged:

Best Answer

  • jsmith
    jsmith Member Posts: 2,856
    edited May 3, 2017 5:58PM Answer ✓

    The problem is that the default setting for a TitledPane is animated transitions for expansion and hiding.  So the content of the TitledPane isn't fully visible until the transition to show the content is complete.  This means that the TextField you are trying to focus on is not visible until later (even when you use Platform.runLater for the focus request, as that just delays the focus request until the pulse or at most 1/60th of a second).  You can make it work by setting animation to false and also using runLater.

    import javafx.application.Application;import javafx.application.Platform;import javafx.scene.Scene;import javafx.scene.control.TextField;import javafx.scene.control.TitledPane;import javafx.scene.layout.AnchorPane;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FocusTest extends Application {    TextField tf = new TextField(), tf2 = new TextField(), tf3 = new TextField();    VBox holder = new VBox(5, tf, tf2, tf3);    TitledPane tp = new TitledPane("Testing",holder);    AnchorPane root = new AnchorPane(tp);    @Override    public void start(Stage primaryStage) {        tp.setExpanded(false);        tp.setAnimated(false);        tp.expandedProperty().addListener((c,o,n)->{            if(n)                Platform.runLater(() -> tf.requestFocus());        });        Scene scene = new Scene(root, 300, 250);        primaryStage.setTitle("Hello World!");        primaryStage.setScene(scene);        primaryStage.show();    }    public static void main(String[] args) {        launch(args);    }}

    Or alternately, if you want to keep the animation, you can update focus based upon the visibility of the titled pane's content:

    import javafx.application.Application;import javafx.scene.Scene;import javafx.scene.control.TextField;import javafx.scene.control.TitledPane;import javafx.scene.layout.AnchorPane;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FocusTest extends Application {    TextField tf = new TextField(), tf2 = new TextField(), tf3 = new TextField();    VBox holder = new VBox(5, tf, tf2, tf3);    TitledPane tp = new TitledPane("Testing",holder);    AnchorPane root = new AnchorPane(tp);    @Override    public void start(Stage primaryStage) {        tp.setExpanded(false);        holder.visibleProperty().addListener((observable, oldValue, isVisible) -> {            if (isVisible) {                tf.requestFocus();            }        });        Scene scene = new Scene(root, 300, 250);        primaryStage.setTitle("Hello World!");        primaryStage.setScene(scene);        primaryStage.show();    }    public static void main(String[] args) {        launch(args);    }}
    Muzib

Answers

  • jsmith
    jsmith Member Posts: 2,856
    edited May 3, 2017 5:58PM Answer ✓

    The problem is that the default setting for a TitledPane is animated transitions for expansion and hiding.  So the content of the TitledPane isn't fully visible until the transition to show the content is complete.  This means that the TextField you are trying to focus on is not visible until later (even when you use Platform.runLater for the focus request, as that just delays the focus request until the pulse or at most 1/60th of a second).  You can make it work by setting animation to false and also using runLater.

    import javafx.application.Application;import javafx.application.Platform;import javafx.scene.Scene;import javafx.scene.control.TextField;import javafx.scene.control.TitledPane;import javafx.scene.layout.AnchorPane;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FocusTest extends Application {    TextField tf = new TextField(), tf2 = new TextField(), tf3 = new TextField();    VBox holder = new VBox(5, tf, tf2, tf3);    TitledPane tp = new TitledPane("Testing",holder);    AnchorPane root = new AnchorPane(tp);    @Override    public void start(Stage primaryStage) {        tp.setExpanded(false);        tp.setAnimated(false);        tp.expandedProperty().addListener((c,o,n)->{            if(n)                Platform.runLater(() -> tf.requestFocus());        });        Scene scene = new Scene(root, 300, 250);        primaryStage.setTitle("Hello World!");        primaryStage.setScene(scene);        primaryStage.show();    }    public static void main(String[] args) {        launch(args);    }}

    Or alternately, if you want to keep the animation, you can update focus based upon the visibility of the titled pane's content:

    import javafx.application.Application;import javafx.scene.Scene;import javafx.scene.control.TextField;import javafx.scene.control.TitledPane;import javafx.scene.layout.AnchorPane;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FocusTest extends Application {    TextField tf = new TextField(), tf2 = new TextField(), tf3 = new TextField();    VBox holder = new VBox(5, tf, tf2, tf3);    TitledPane tp = new TitledPane("Testing",holder);    AnchorPane root = new AnchorPane(tp);    @Override    public void start(Stage primaryStage) {        tp.setExpanded(false);        holder.visibleProperty().addListener((observable, oldValue, isVisible) -> {            if (isVisible) {                tf.requestFocus();            }        });        Scene scene = new Scene(root, 300, 250);        primaryStage.setTitle("Hello World!");        primaryStage.setScene(scene);        primaryStage.show();    }    public static void main(String[] args) {        launch(args);    }}
    Muzib
  • Muzib
    Muzib Member Posts: 10
    edited May 5, 2017 3:04PM

    wow!! that was really helpful.. Thanks a lot for a detailed answer.

This discussion has been closed.