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

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

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

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

对于更复杂的效果,请看一下。

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

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

我建议看看分页控件。

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