java 具有幻灯片效果的 JavaFX 切换场景
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27089627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaFX Switch scene with slide effect
提问by Emax
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?
我希望当我在舞台实例上调用 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);
}
}
回答by José Pereda
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.
您不能在两个场景之间应用过渡,因为不可能在一个舞台上同时进行两个场景。一种解决方案是只有一个场景并管理内部的所有转换,如@James_D 的答案。
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.
对于更复杂的效果,看看这个。
回答by James_D
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.
AStage
可以包含一个并且只有一个Scene
,并且每个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);
}
}
回答by dreamsComeTrue
AFAIK it's not possible. Rather than sliding scenes, try creating different layouts inside one scene and slide between them.
AFAIK 这是不可能的。与其滑动场景,不如尝试在一个场景中创建不同的布局并在它们之间滑动。
回答by eckig
I would recommend having a look at the Paginationcontrol.
我建议看看分页控件。
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.
它用动画切换其内容窗格。您可以自定义它以满足您的需求,也可以查看其皮肤实现以了解如何制作动画。