9 Replies Latest reply: Mar 16, 2012 9:41 AM by 907516 RSS

    transition between scenes

    907516
      Hi! Is it possible to apply a transition effect during a scene swap within a stage?
      Stage stage = new Stage();
      
      stage.setScene(new SceneA());
      // I'd like to show a transition effect during this swap
      stage.setScene(new SceneB());
      Edited by: redcloud on Mar 12, 2012 9:33 PM
        • 1. Re: transition between scenes
          JohnHendrikx
          Put both scenes in a StackPane and use the StackPane as the scene root.

          Then do something like this:
          StackPane stackPane = new StackPane();
          
          stackPane.add(oldScene);
          stackPane.add(newScene);
          
          oldScene.setOpacity(1.0);
          newScene.setOpacity(0.0);
          
          scene.setRoot(stackPane);
          
          Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(0), new KeyValue(oldScene.opacityProperty(), 1.0), new KeyValue(newScene.opacityProperty(), 0.0)),
            new KeyFrame(Duration.seconds(2), new KeyValue(oldScene.opacityProperty(), 0.0), new KeyValue(newScene.opacityProperty(), 1.0))
          };
          
          timeline.play();
          • 2. Re: transition between scenes
            907516
            It seems impossible to add a Scene to a StackPane...
            • 3. Re: transition between scenes
              JohnHendrikx
              The name of the variables I use is confusing, I don't mean the Scene, I mean the root of the Scene.
              • 4. Re: transition between scenes
                shakir.gusaroff
                Hi. Take a look at this example:
                import javafx.application.Application;
                import javafx.event.ActionEvent;
                import javafx.event.EventHandler;
                import javafx.scene.Group;
                import javafx.scene.Scene;
                import javafx.scene.layout.*;
                import javafx.scene.control.*;
                import javafx.stage.Stage;
                import javafx.animation.*;
                import javafx.scene.layout.VBoxBuilder;
                import javafx.scene.text.TextBuilder;
                import javafx.util.*;
                
                public class AnimatedScenes extends Application {
                
                    VBox page1 = null;
                    VBox page2 = null;
                    Timeline timeline1 = null;
                    Timeline timeline2 = null;
                
                    /**
                     * @param args the command line arguments
                     */
                    public static void main(String[] args) {
                        Application.launch(args);
                    }
                
                    @Override
                    public void start(final Stage primaryStage) {
                
                
                        primaryStage.setTitle("Hello World");
                
                        final Group root = new Group();
                        final Scene scene = new Scene(root, 300, 250);
                        page1 = VBoxBuilder.create()
                                .spacing(10)
                                .children(TextBuilder.create()
                                .text("Home page").build(),
                                ButtonBuilder.create()
                                .text("Login")
                                .onAction(new EventHandler<ActionEvent>() {
                
                            @Override
                            public void handle(ActionEvent e) {
                                root.getChildren().remove(page1);
                                timeline1.play();
                                root.getChildren().add(page2);
                            }
                        }).build())
                        .build();
                
                
                
                        page2 = VBoxBuilder.create()
                                .spacing(10)
                                .children(TextFieldBuilder.create()
                                .text("")
                                .build(),
                                ButtonBuilder.create()
                                .text("Go to home page")
                                .onAction(new EventHandler<ActionEvent>() {
                
                            @Override
                            public void handle(ActionEvent e) {
                                root.getChildren().remove(page2);
                                timeline2.play();
                                root.getChildren().add(page1);
                            }
                        }).build()).build();
                
                
                        root.getChildren().add(page1);
                
                        timeline1 = new Timeline(
                                new KeyFrame(Duration.seconds(0), new KeyValue(page2.opacityProperty(), 0.0)),
                                new KeyFrame(Duration.seconds(3), new KeyValue(page2.opacityProperty(), 1.0)));
                
                
                
                        timeline2 = new Timeline(
                                new KeyFrame(Duration.seconds(0), new KeyValue(page1.opacityProperty(), 0.0)),
                                new KeyFrame(Duration.seconds(3), new KeyValue(page1.opacityProperty(), 1.0)));
                
                        primaryStage.setScene(scene);
                        primaryStage.show();
                    }
                }
                • 5. Re: transition between scenes
                  JohnHendrikx
                  I meant more like this. With a StackPane you can get the transition to happen with both pages temporarily visible at once in some fashion (in this case a cross fade).
                  import javafx.animation.KeyFrame;
                  import javafx.animation.KeyValue;
                  import javafx.animation.Timeline;
                  import javafx.application.Application;
                  import javafx.event.ActionEvent;
                  import javafx.event.EventHandler;
                  import javafx.scene.Parent;
                  import javafx.scene.Scene;
                  import javafx.scene.control.ButtonBuilder;
                  import javafx.scene.control.TextFieldBuilder;
                  import javafx.scene.layout.StackPane;
                  import javafx.scene.layout.VBox;
                  import javafx.scene.layout.VBoxBuilder;
                  import javafx.scene.text.TextBuilder;
                  import javafx.stage.Stage;
                  import javafx.util.Duration;
                  
                  public class AnimatedScenes extends Application {
                  
                      StackPane stackPane = new StackPane();
                      VBox page1 = null;
                      VBox page2 = null;
                  
                      /**
                       * @param args the command line arguments
                       */
                      public static void main(String[] args) {
                          Application.launch(args);
                      }
                  
                      @Override
                      public void start(final Stage primaryStage) {
                  
                          primaryStage.setTitle("Hello World");
                  
                          final Scene scene = new Scene(stackPane, 300, 250);
                  
                          page1 = VBoxBuilder.create()
                                  .spacing(10)
                                  .children(TextBuilder.create()
                                  .text("Home page").build(),
                                  ButtonBuilder.create()
                                  .text("Login")
                                  .onAction(new EventHandler<ActionEvent>() {
                  
                              @Override
                              public void handle(ActionEvent e) {
                                switchPage(page2);
                              }
                          }).build())
                          .build();
                  
                          stackPane.getChildren().add(page1);
                  
                          page2 = VBoxBuilder.create()
                                  .spacing(10)
                                  .children(TextFieldBuilder.create()
                                  .text("")
                                  .build(),
                                  ButtonBuilder.create()
                                  .text("Go to home page")
                                  .onAction(new EventHandler<ActionEvent>() {
                  
                              @Override
                              public void handle(ActionEvent e) {
                                  switchPage(page1);
                              }
                          }).build()).build();
                  
                          primaryStage.setScene(scene);
                          primaryStage.show();
                      }
                  
                      private void switchPage(Parent newPage) {
                        stackPane.getChildren().add(newPage);
                  
                        EventHandler<ActionEvent> finished = new EventHandler<ActionEvent>() {
                          @Override
                          public void handle(ActionEvent event) {
                            stackPane.getChildren().remove(0);
                          }
                        };
                  
                        final Timeline switchPage = new Timeline(
                          new KeyFrame(Duration.seconds(0), new KeyValue(stackPane.getChildren().get(1).opacityProperty(), 0.0), new KeyValue(stackPane.getChildren().get(0).opacityProperty(), 1.0)),
                          new KeyFrame(Duration.seconds(3), finished, new KeyValue(stackPane.getChildren().get(1).opacityProperty(), 1.0), new KeyValue(stackPane.getChildren().get(0).opacityProperty(), 0.0))
                        );
                  
                        switchPage.play();
                      }
                  }
                  • 6. Re: transition between scenes
                    907516
                    Thank you all for your tips. I found this solution
                    private void launchClient() {
                              int stageWidth = Main.getSettings().getClientWidth();
                              int stageHeight = Main.getSettings().getClientHeight();
                    
                              // if (stageWidth == 0 || stageHeight == 0) {
                              // stageWidth =
                              // }
                              //
                              // stage.setTitle(Constants.SHORT_TITLE);
                    
                              StackPane stackPane = new StackPane();
                    
                              Pane logoPane = new LogoPane(stage, 1280, 768);
                              Pane mainPane = new MainPane(stage, 1280, 700);
                    
                              stackPane.getChildren().add(mainPane);
                              stackPane.getChildren().add(logoPane);
                    
                              logoPane.setOpacity(1);
                              mainPane.setOpacity(1);
                    
                              final Timeline timeline1 = new Timeline(new KeyFrame(Duration.seconds(0), new KeyValue(stage.opacityProperty(), 0.0)), new KeyFrame(
                                        Duration.seconds(2), new KeyValue(stage.opacityProperty(), 1.0)));
                    
                              final TranslateTransition transition = new TranslateTransition(Duration.seconds(1), logoPane);
                              transition.setFromY(0);
                              transition.setToY(768);
                              transition.setInterpolator(Interpolator.SPLINE(0.5, 1, 1, 0));
                              transition.setDelay(Duration.seconds(1.5));
                    
                              final SequentialTransition st = new SequentialTransition(timeline1, transition);
                    
                              Scene root = new Scene(stackPane, 1280, 768, Color.BLACK);
                    
                              stage.setOnShown(new EventHandler<WindowEvent>() {
                    
                                   @Override
                                   public void handle(WindowEvent arg0) {
                                        st.play();
                                   }
                              });
                              stage.setScene(root);
                              stage.setResizable(false);
                              stage.initStyle(StageStyle.UNDECORATED);
                              stage.show();
                         }
                    • 7. Re: transition between scenes
                      907516
                      I think I've found a little issue with setOnFinished applied to a Transition.
                      transition.setOnFinished(new EventHandler<ActionEvent>() {
                           @Override
                           public void handle(ActionEvent arg0) {
                                // cpu consuming task
                           }
                      });
                      What I'm expecting from this code is that once the transition is completed, the cpu consuming task will start.
                      What I notice however is that the transition is interrupted just before the end (I mean on the gui painting side, some artifacts will remain painted). It looks like that the handle method doesn't take into account the time spent for the graphics refresh. If I remove the cpu consuming task, the transition looks good. How to solve?
                      • 8. Re: transition between scenes
                        jsmith
                        If it is not already, make the cpu consuming task a Task and return from the handle method as quickly as possible, while the cpu consuming Task is executed in parallel.
                        http://docs.oracle.com/javafx/2.0/api/javafx/concurrent/Task.html
                        • 9. Re: transition between scenes
                          907516
                          It could be a good workaround but it's not acceptable for me.