具有幻灯片效果的JavaFX Switch场景

时间:2014-11-23 13:46:52

标签: java animation javafx

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

当我在舞台实例上调用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);
    }
}

4 个答案:

答案 0 :(得分:7)

您无法在两个场景之间应用过渡,因为在一个舞台上无法同时进行这两个过渡。一种解决方案是只有一个场景并管理内部的所有过渡,如@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

答案 1 :(得分:4)

Stage可以包含一个且只有一个Scene,每个Scene只有一个根。{1}}。因此,您需要在单个场景的根目录内管理转换。

简单示例:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我建议您查看Pagination控件。

它用动画切换其内容窗格。您可以自定义此选项以满足您的需求,也可以查看其外观实现,以了解如何进行动画制作。