5

In JavaFx, I want to show a modal dialog after an animation ends. For some reason, calling showAndWait in the EventHandler that gets executed after the animation ends doesn't work. A new window is shown, but it seems like nothing is drawn inside it.

This example demonstrates the issue:

public void start(Stage primaryStage) {
    Rectangle rect = RectangleBuilder.create().width(200).height(200).fill(Color.RED).build();

    StackPane root = new StackPane();
    root.getChildren().add(rect);

    Timeline animation = new Timeline();
    animation.getKeyFrames().addAll(
            new KeyFrame(new Duration(1000),
                         new KeyValue(rect.widthProperty(), 100),
                         new KeyValue(rect.heightProperty(), 100)),
            new KeyFrame(new Duration(2000),
                         new KeyValue(rect.widthProperty(), 300),
                         new KeyValue(rect.heightProperty(), 300))
    );
    animation.setOnFinished(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent t) {
            Stage stage = new Stage();
            StackPane pane = new StackPane();
            pane.getChildren().add(new Label("Hello world"));
            stage.setScene(new Scene(pane, 100, 100));
            stage.showAndWait();
        }
    });
    animation.setCycleCount(1);

    Scene scene = new Scene(root, 300, 300);
    primaryStage.setScene(scene);
    primaryStage.show();

    animation.play();
}

The full code can be found at https://gist.github.com/bmesuere/9605866

I'd like to know why this doesn't work (on my macbook using java 1.7.0_51) and get suggestions for a workaround.

bmesuere
  • 502
  • 3
  • 12

2 Answers2

4

It seems to work if you wrap the code to show the stage in a Platform.runLater():

animation.setOnFinished(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        Stage stage = new Stage();
                        StackPane pane = new StackPane();
                        pane.getChildren().add(new Label("Hello world"));
                        stage.setScene(new Scene(pane, 100, 100));
                        stage.showAndWait();                        
                    }
                });

            }
        });

No idea why. It fails on Java FX 8 too.

James_D
  • 201,275
  • 16
  • 291
  • 322
1

I have reported this as a bug in JavaFX (Jira issue).

A comment from that issue:

The problem is that no subsequent pulse is scheduled when showAndWait() is called while pulse is being processed.

This was 'fixed' in Java 8u20. An exception is now thrown. Changes can be seen here.

bmesuere
  • 502
  • 3
  • 12
  • I figured it was something like that. I tend to avoid using showAndWait() if possible; you can usually use show() and register a handler with the Stage's showing property to achieve what you need. – James_D Mar 18 '14 at 13:31
  • Hey @bmesuere ! do you have any idea if the issue is fixed ! thanks . – zoey3 Jun 08 '15 at 08:56
  • This was 'fixed' in Java 8u20. An exception is now thrown: http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/c5ebcc5268b4 – bmesuere Jun 08 '15 at 13:06