【问题标题】:JavaFX Switch scene with slide effect带有幻灯片效果的 JavaFX Switch 场景
【发布时间】:2015-01-21 06:25:06
【问题描述】:

可以用幻灯片效果切换场景吗?

我希望当我在舞台实例上调用 setScene 时 它用幻灯片效果改变场景。有可能吗?

public class ManyScenes extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(final Stage primaryStage) {
        primaryStage.setTitle("Slide");

        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.setScene(scene1);
        primaryStage.show();

        // Here i  need a slide effect,
        // this method is called when a button is pressed.
        primaryStage.setScene(scene2);
    }
}

【问题讨论】:

  • 您需要幻灯片效果还是想知道它是否可行?

标签: java animation javafx


【解决方案1】:

您不能在两个场景之间应用过渡,因为不可能在一个舞台上同时拥有两个场景。一种解决方案是只有一个场景并管理内部的所有过渡,如@James_D 的回答。

但您也可以模拟两个场景之间的过渡。为此,您可以使用两者的两个快照,在它们之间执行转换,最后只需设置新场景。

这是一个非常基本的工作案例,您只需在新场景中单击即可再次前后移动:

@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();
    });

}

如需更复杂的效果,请查看this

【讨论】:

    【解决方案2】:

    一个Stage 可以包含一个且只有一个Scene,每个Scene 有一个且只有一个根。所以你需要在单个场景的根中管理过渡。

    简单示例:

    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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我建议您查看Pagination 控件。

      它使用动画切换其内容窗格。您可以自定义这个以满足您的需求,或者查看它的皮肤实现以了解如何制作动画。

      【讨论】:

        【解决方案4】:

        AFAIK 这是不可能的。与其滑动场景,不如尝试在一个场景中创建不同的布局并在它们之间滑动。

        【讨论】:

        • 先生,这应该是评论还是?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-16
        • 1970-01-01
        • 2014-05-11
        • 1970-01-01
        • 2015-03-08
        • 1970-01-01
        • 2012-07-02
        相关资源
        最近更新 更多