JavaFX Switch scene with slide effect

后端 未结 4 1273
既然无缘
既然无缘 2020-12-14 12:58

Is possible to switch scene with a slide effect?

i want that when i call the setScene on the stage instance it change the scene with a slide effect. it\'s possible?<

相关标签:
4条回答
  • 2020-12-14 13:24

    A Stage can contain one and only one Scene, and each Scene has one and only one root. So you need to manage the transition inside the root of a single scene.

    Simple example:

    import javafx.animation.KeyFrame;
    import javafx.animation.KeyValue;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class SlidingViews extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            Rectangle rectangle1 = new Rectangle(300, 250);
            rectangle1.setFill(Color.RED);
    
            Button nextView = new Button("Next");
            nextView.setPadding(new Insets(10));
            BorderPane view1 = new BorderPane(rectangle1, null, null, nextView, null);
            BorderPane.setAlignment(nextView, Pos.CENTER);
    
            Group view2 = new Group();
            Rectangle rectangle2 = new Rectangle(300, 250);
            rectangle2.setFill(Color.BLUE);
            view2.getChildren().add(rectangle2);
    
            StackPane root = new StackPane(view1);
    
            nextView.setOnAction(event -> {
                root.getChildren().add(view2);
                double width = root.getWidth();
                KeyFrame start = new KeyFrame(Duration.ZERO,
                        new KeyValue(view2.translateXProperty(), width),
                        new KeyValue(view1.translateXProperty(), 0));
                KeyFrame end = new KeyFrame(Duration.seconds(1),
                        new KeyValue(view2.translateXProperty(), 0),
                        new KeyValue(view1.translateXProperty(), -width));
                Timeline slide = new Timeline(start, end);
                slide.setOnFinished(e -> root.getChildren().remove(view1));
                slide.play();
            });
    
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 13:31

    AFAIK it's not possible. Rather than sliding scenes, try creating different layouts inside one scene and slide between them.

    0 讨论(0)
  • 2020-12-14 13:36

    I would recommend having a look at the Pagination control.

    It switches its content panes with an animation. You can either customize this one to fit your needs or have a look at its skin implementation to get an idea on how to do the animation.

    0 讨论(0)
  • 2020-12-14 13:43

    You can't apply a transition between two scenes, as it is not possible to have both at the same time on one stage. One solution would be having just one scene and manage all the transitions inside, as in @James_D answer.

    But you could also simulate a transition between two scenes. For this you can use two snapshots of both, perform a transition between those and at the end just set the new scene.

    This is a very basic working case, where you can go backwards and forward all over again just clicking in the new scene:

    @Override
    public void start(Stage primaryStage) {
        Group root1 = new Group();
        Group root2 = new Group();
    
        Scene scene1 = new Scene(root1, 300, 250);
        Scene scene2 = new Scene(root2, 300, 250);
    
        Rectangle rectangle2 = new Rectangle(300, 250);
        rectangle2.setFill(Color.BLUE);
        root2.getChildren().add(rectangle2);
    
        Rectangle rectangle1 = new Rectangle(300, 250);
        rectangle1.setFill(Color.RED);
        root1.getChildren().add(rectangle1);
    
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene1);
        primaryStage.show();
    
        rectangle1.setOnMouseClicked(e->{
            // Create snapshots with the last state of the scenes
            WritableImage wi = new WritableImage(300, 250);
            Image img1 = root1.snapshot(new SnapshotParameters(),wi);
            ImageView imgView1= new ImageView(img1);
            wi = new WritableImage(300, 250);
            Image img2 = root2.snapshot(new SnapshotParameters(),wi);
            ImageView imgView2= new ImageView(img2);
            // Create new pane with both images
            imgView1.setTranslateX(0);
            imgView2.setTranslateX(300);
            StackPane pane= new StackPane(imgView1,imgView2);
            pane.setPrefSize(300,250);
            // Replace root1 with new pane
            root1.getChildren().setAll(pane);
            // create transtition
            Timeline timeline = new Timeline();
            KeyValue kv = new KeyValue(imgView2.translateXProperty(), 0, Interpolator.EASE_BOTH);
            KeyFrame kf = new KeyFrame(Duration.seconds(1), kv);
            timeline.getKeyFrames().add(kf);
            timeline.setOnFinished(t->{
                // remove pane and restore scene 1
                root1.getChildren().setAll(rectangle1);
                // set scene 2
                primaryStage.setScene(scene2);
            });
            timeline.play();
        });
        rectangle2.setOnMouseClicked(e->{
            // Create snapshots with the last state of the scenes
            WritableImage wi = new WritableImage(300, 250);
            Image img1 = root1.snapshot(new SnapshotParameters(),wi);
            ImageView imgView1= new ImageView(img1);
            wi = new WritableImage(300, 250);
            Image img2 = root2.snapshot(new SnapshotParameters(),wi);
            ImageView imgView2= new ImageView(img2);
            // Create new pane with both images
            imgView2.setTranslateX(0);
            imgView1.setTranslateX(300);
            StackPane pane= new StackPane(imgView2,imgView1);
            pane.setPrefSize(300,250);
            // Replace root2 with new pane
            root2.getChildren().setAll(pane);
            // create transtition
            Timeline timeline = new Timeline();
            KeyValue kv = new KeyValue(imgView1.translateXProperty(), 0, Interpolator.EASE_BOTH);
            KeyFrame kf = new KeyFrame(Duration.seconds(1), kv);
            timeline.getKeyFrames().add(kf);
            timeline.setOnFinished(t->{
                // remove pane and restore scene 2
                root2.getChildren().setAll(rectangle2);
                // set scene 1
                primaryStage.setScene(scene1);
            });
            timeline.play();
        });
    
    }
    

    For more complex effects have a look at this.

    0 讨论(0)
提交回复
热议问题