Implement side-scrolling like transitions between scenes [duplicate] - java

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

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.

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

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

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.

Related

primaryStage cannot be resolved to a variable:,When using in other class: JavaFX

I know There are many Questions related to this particular error, But I couldn't Find a solution that fits my Error.
So What I am doing is creating a javaFX Application and using the Modality library so that I can create a subwindow which opens always above of the Primary Stage. But the Error I am getting that I am not able set the primaryStage Variable inside the initOwner() function because of the Scope issue as PrimaryStage is outside the scope of SubModal Class.
let me put some code to make things clear..
//SubModal Class
class SubModal extends singleModal {
SubModal()
{
Stage subStage1 = new Stage();
subStage1.setTitle("New Stage1");
FlowPane root = new FlowPane();
root.setAlignment(Pos.CENTER);
Scene scene1 = new Scene(root, 300, 200);
Button btn2 = new Button("Button: Stage1");
root.getChildren().add(btn2);
btn2.setOnAction(eve-> System.out.println("Clicked on Stage 1 Button"));
subStage1.initOwner(primaryStage);
subStage1.initModality(Modality.NONE);
subStage1.setScene(scene1);
subStage1.show();
}
}
//SingleModal Class
public class singleModal extends Application {
public static void main(String[] args) {
Application.launch(args);
}
public void start(Stage primaryStage) {
primaryStage.setTitle("PrimaryStage");
FlowPane root = new FlowPane();
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 700, 200);
Button btn = new Button("Open New Stage");
btn.setOnAction(eve-> new NewStage());
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
}
}
From the above code..
subStage1.initOwner(primaryStage);
This particular line Shows the Error
primaryStage cannot be resolved to a variable
I Know it's because PrimaryStage() is not available in the subModal Class.
So My question is that How Can I fix this issue in JavaFX. How can I bring the primaryStage Value in the SubModal Class so that I can run this Code ErrorFree
For the needed functionality ("create a subwindow which opens always above of the Primary Stage") there is no need to extend singleModal.
Here is an mre demonstrating it:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class SingleModal extends Application {
#Override
public void start(Stage primaryStage) {
Stage subStage1 = new Stage();
subStage1.setTitle("New Stage1");
Button btn2 = new Button("Button: Stage1");
FlowPane root2 = new FlowPane();
root2.setAlignment(Pos.CENTER);
root2.getChildren().add(btn2);
btn2.setOnAction(eve-> System.out.println("Clicked on Stage 1 Button"));
subStage1.initOwner(primaryStage);
subStage1.initModality(Modality.NONE);
Scene scene1 = new Scene(root2, 300, 200);
subStage1.setScene(scene1);
primaryStage.setTitle("PrimaryStage");
FlowPane root = new FlowPane();
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 700, 200);
Button btn = new Button("Open New Stage");
btn.setOnAction(eve-> subStage1.show());
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
I think what u want is just add the code in the start method. I have no idea what the SubModule class is for.
Further Modality is not a library. Maybe call it a feature.
Maybe that example helps http://java-buddy.blogspot.com/2013/08/javafx-example-modality.html .
So add
Stage subStage1 = new Stage();
subStage1.setTitle("New Stage1");
FlowPane root = new FlowPane();
root.setAlignment(Pos.CENTER);
Scene scene1 = new Scene(root, 300, 200);
Button btn2 = new Button("Button: Stage1");
root.getChildren().add(btn2);
btn2.setOnAction(eve-> System.out.println("Clicked on Stage 1 Button"));
subStage1.initOwner(primaryStage);
subStage1.initModality(Modality.NONE);
subStage1.setScene(scene1);
subStage1.show();
to the end of the start method.

How do I create a JavaFX BorderPane with no center?

I would like to create a BorderPane layout in JavaFX with no center pane.
The code I have written so far only implements the left and right borders and is below:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class GUI_Practice extends Application {
#Override
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
/* Left column */
Button save = new Button("Save");
Button del = new Button("Delete");
HBox settings = new HBox(save, del);
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
/* Right column */
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
/* Set up borderpane */
BorderPane root = new BorderPane();
root.setPadding(new Insets(15));
root.setLeft(leftCol);
root.setRight(rightCol);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
The output it gives is shown in the image below:
However, I want it to look more like this:
Where the left and right columns are equal width and take up the entire width of the window. Additionally, the columns do not change width with the window, so the whitespace in the middle gets bigger as the window gets bigger.
What do I need to change to make the columns fill the width of the window?
(P.S. I'm still learning, so if the solution could avoid FXML (which I don't understand yet), that'd be great)
EDIT: as per #k88's suggestion, my start method now looks like so:
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
Button save = new Button("Save");
Button del= new Button("Delete");
HBox settings = new HBox(save, load);
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
HBox root = new HBox(leftCol, rightCol);
root.setPadding(new Insets(15));
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
Giving a window looking like:
There are different ways to get this problem fixed.
If you want to still gain the benefits from BorderPane (like to have top and bottom panes), you can set a HBox/GridPane as the center (without setting left/right).
If you are not bothered about top and bottom layout implementations, then as #k88 suggested, you can use directly HBox or GridPane as your root node.
Using HBox:
HBox.setHGrow(leftCol,Priority.ALWAYS);
HBox.setHGrow(rightCol,Priority.ALWAYS);
HBox root = new HBox();
root.setPadding(new Insets(15));
root.getChildren().addAll(leftCol, rightCol);
Using GridPane:
GridPane root = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(50);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(50);
root.getColumnConstraints().addAll(col1,col2);
root.addRow(0, leftCol,rightCol);
Update: In either cases, if you want your buttons to auto stretch, bind the width of the buttons to its layout. This way you can control the buttons width proportion in the HBox.
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
calculate.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
cancel.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
Update 2: Please find below a sample demo.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class Sample extends Application {
public void start(Stage stage) throws Exception {
String blackBorder = "-fx-border-style: solid; -fx-border-width: 1; -fx-border-color: black";
Button calculate = new Button("Calculate");
Button cancel = new Button("Cancel");
HBox runButtons = new HBox(calculate, cancel);
calculate.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
cancel.prefWidthProperty().bind(runButtons.widthProperty().divide(2));
VBox rightCol = new VBox(runButtons);
rightCol.setStyle(blackBorder);
Button save = new Button("Save");
Button del = new Button("Delete");
HBox settings = new HBox(save, del);
save.prefWidthProperty().bind(settings.widthProperty().divide(3)); // 1/3
del.prefWidthProperty().bind(settings.widthProperty().divide(3).multiply(2)); // 2/3
VBox leftCol = new VBox(settings);
leftCol.setStyle(blackBorder);
GridPane root = new GridPane();
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(50);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(50);
root.getColumnConstraints().addAll(col1,col2);
root.addRow(0, leftCol,rightCol);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String... a) {
Application.launch(a);
}
}

JavaFX - Animate along path parallel to tangent

I'm trying to get a car to animate along a curved path. The PathTransition.OrientationType only seems to give the option to keep the node perpendicular to the path instead of parallel.
Is there a way to make this parallel?
Here is a bit of what I have so far:
VBox car = new VBox();
Line track1 = new Line(242, 10, 242, 200);
Line track2 = new Line(258, 10, 258, 200);
Line track3 = new Line(242, 600, 242, 800);
Line track4 = new Line(258, 600, 258, 800);
CubicCurveTo curvePath1 = new CubicCurveTo();
curvePath1.setControlX1(400.0f);
curvePath1.setControlY1(300.0f);
curvePath1.setControlX2(400.0f);
curvePath1.setControlY2(500.0f);
curvePath1.setX(250.0f);
curvePath1.setY(600.0f);
VBox station1 = new VBox();
LoadingPosition stationUp = new LoadingPosition();
LoadingPosition stationDown = new LoadingPosition();
station1.getChildren().addAll(stationUp, stationDown);
station1.setLayoutX(170);
station1.setLayoutY(27);
VBox station2 = new VBox();
LoadingPosition station2Up = new LoadingPosition();
LoadingPosition station2Down = new LoadingPosition();
station2.getChildren().addAll(station2Up, station2Down);
station2.setLayoutX(170);
station2.setLayoutY(712);
//Setting up the path
Path path = new Path();
path.getElements().add(new MoveTo(250f, 70f));
path.getElements().add(new LineTo(250f, 200f));
path.getElements().add(curvePath1);
path.getElements().add(new LineTo(250f, 712f));
//Instantiating PathTransition class
PathTransition pathTransition = new PathTransition();
//Setting duration for the PathTransition
pathTransition.setDuration(Duration.millis(1000));
//Setting Node on which the path transition will be applied
pathTransition.setNode(car);
//setting path for the path transition
pathTransition.setPath(path);
//setting up the cycle count
pathTransition.setCycleCount(10);
//setting auto reverse to be true
pathTransition.setAutoReverse(true);
pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
//Playing path transition
pathTransition.play();
//Applying parallel Translation to the circle
ParallelTransition parallelTransition = new ParallelTransition(
car, pathTransition);
//Playing the animation
parallelTransition.play();
//Configuring group and scene
Group root = new Group();
root.getChildren().addAll(station1, station2, track1, track2, track3, track4, curveTrack1, curveTrack2, car, path);
Scene scene = new Scene(root, 1200, 900, Color.LIGHTGRAY);
primaryStage.setScene(scene);
primaryStage.setTitle("Path Transition Example");
primaryStage.show();
}
Orthogonal to path instead of parallel
Altered code from here
imp
ort javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
import javafx.util.Duration;
public class JavaFXApplication extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(Stage primaryStage)
{
primaryStage.setTitle("PathTransition");
Group root = new Group();
Scene scene = new Scene(root, 800, 300, Color.GREY);
//ImageView car = new ImageView(new Image("http://hajsoftutorial.com/im/smallcar.png"));
Image image = new Image(getClass().getResourceAsStream("car.png"));
ImageView car = new ImageView(image);
car.setFitHeight(40);
car.setPreserveRatio(true);
Path road = new Path();
road.setStrokeWidth(30);
MoveTo moveTo = new MoveTo();
moveTo.setX(150);
moveTo.setY(30);
LineTo line1 = new LineTo();
line1.setX(650);
line1.setY(30);
CubicCurveTo cubicTo = new CubicCurveTo();
cubicTo.setControlX1(800);
cubicTo.setControlY1(30);
cubicTo.setControlX2(800);
cubicTo.setControlY2(270);
cubicTo.setX(650);
cubicTo.setY(270);
LineTo line2 = new LineTo();
line2.setX(150);
line2.setY(270);
CubicCurveTo cubicTo2 = new CubicCurveTo();
cubicTo2.setControlX1(0);
cubicTo2.setControlY1(270);
cubicTo2.setControlX2(0);
cubicTo2.setControlY2(30);
cubicTo2.setX(150);
cubicTo2.setY(30);
road.getElements().addAll(moveTo, line1, cubicTo, line2, cubicTo2);
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(10000));
pathTransition.setNode(car);
pathTransition.setPath(road);
pathTransition.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
pathTransition.setCycleCount(Timeline.INDEFINITE);
pathTransition.play();
root.getChildren().addAll(road, car);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I was able to get it working by trying other ways to rotate the car, thanks to Fabian for suggesting.
Sedrick's example also helped narrow down where to focus.
Here's what I added:
car.getTransforms().add(new Rotate(270,totalCarHeight/2,totalCarWidth));
The pivot points were a little unusual, but this made it perfectly centered on the path.
Previously, I tried:
car.setRotate(270);
Which did nothing, leading me to drift away from that idea.

How to preserve image ratio and resize image according to its actual size?

I have searched and googled a lot but can't find a simple solution to this. I want to resize the image according to its actual size and preserving the image ratio at the same time. As you can see from the following sample code, with the preserveRatio property set to true, I am able to resize the image. However, as I resize pass the actual width or height of the image, a white space will appear. How can I resize it without the appearance of the white space?
package test;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application {
private ImageView imageView = new ImageView();
#Override
public void start(Stage primaryStage) {
imageView.setImage(new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg"));
imageView.preserveRatioProperty().set(true);
StackPane root = new StackPane();
root.getChildren().add(imageView);
imageView.fitHeightProperty().bind(root.heightProperty());
imageView.fitWidthProperty().bind(root.widthProperty());
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Test Image Resizing");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
You also need to adjust the viewport to make it's dimentions have the correct ratio to fill the whole area with a ImageView:
#Override
public void start(Stage primaryStage) {
imageView.setImage(new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg"));
imageView.setPreserveRatio(true);
StackPane root = new StackPane();
root.getChildren().add(imageView);
root.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
double w = newValue.getWidth();
double h = newValue.getHeight();
imageView.setFitWidth(w);
imageView.setFitHeight(h);
double ratio = h / w;
Image image = imageView.getImage();
double ih = image.getHeight();
double iw = image.getWidth();
double vR = ih / iw;
imageView.setViewport((ratio < vR) ? new Rectangle2D(0, 0, iw, iw * ratio) : new Rectangle2D(0, 0, ih / ratio, ih));
});
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Test Image Resizing");
primaryStage.setScene(scene);
primaryStage.show();
}
In this case you can achieve the same effect by using the image as background image for root:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.setBackground(new Background(
new BackgroundImage(new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg"),
BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(0, 0, false, false, false, true)
)));
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Test Image Resizing");
primaryStage.setScene(scene);
primaryStage.show();
}

JavaFX Stage wont show in Android

I have deployed a JavaFX application in Android using Gluon Plugin. What Im trying to do right now is to show a second Stage, but unfortunately it wont show.
Here's the code of the second Stage:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Setting {
public Setting(){
Text title = new Text("Settings");
title.setId("setting-title");
title.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.04)));
Label label_url = new Label("URL");
label_url.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
Label label_style = new Label("Style");
label_style.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
TextField text_url = new TextField(MainApp.URL);
text_url.setFont(Font.font("Arial", (int)(MainApp.HEIGHT * 0.03)));
ComboBox style_box = new ComboBox();
style_box.setStyle("-fx-font-size:"+(int)(MainApp.HEIGHT * 0.03)+"px;");
ObservableList<String> data = FXCollections.observableArrayList();
data.add("Blue");
data.add("Red");
data.add("Yellow");
style_box.setItems(data);
GridPane grid = new GridPane();
grid.setVgap(5);
grid.setHgap(5);
grid.add(label_url, 0, 0);
grid.add(label_style, 0, 1);
grid.add(text_url, 1, 0);
grid.add(style_box, 1, 1);
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(title,grid);
Scene scene = new Scene(root, MainApp.WIDTH * 0.6, MainApp.HEIGHT * 0.4);
if(MainApp.SETTING == null){
MainApp.SETTING = new Stage();
MainApp.SETTING.setScene(scene);
MainApp.SETTING.initOwner(MainApp.MAINSTAGE);
MainApp.SETTING.setTitle("Settings");
}
}
public void show(){
if(!MainApp.SETTING.isShowing()) MainApp.SETTING.show();
}
}
This code works when I tried to run it as a desktop application. Im using Android 4.2.
Using JavaFXPorts you can change scenes and stages while running on Android.
I've modified the Gluon plugin for NetBeans default sample to achieve this, first switching scenes:
private Scene mainScene;
#Override
public void start(Stage stage) {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Label label = new Label("Main Scene");
StackPane root = new StackPane(label);
mainScene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(mainScene);
stage.show();
label.setOnMouseClicked(e->{
Label labelSettings = new Label("Settings Scene. Click to go back");
StackPane rootSettings = new StackPane(labelSettings);
Scene settingsScene = new Scene(rootSettings, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(settingsScene);
labelSettings.setOnMouseClicked(t->stage.setScene(mainScene));
});
}
Now switching stages:
private Scene mainScene;
#Override
public void start(Stage stage) {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Label label = new Label("Main Stage");
StackPane root = new StackPane(label);
root.setStyle("-fx-background-color: aquamarine;");
mainScene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
stage.setScene(mainScene);
stage.setTitle("Main Stage");
stage.show();
label.setOnMouseClicked(e->{
Label labelSettings = new Label("Settings Stage. Click to go back");
StackPane rootSettings = new StackPane(labelSettings);
rootSettings.setStyle("-fx-background-color: burlywood;");
Scene settingsScene = new Scene(rootSettings, visualBounds.getWidth(), visualBounds.getHeight());
Stage stage2 = new Stage();
stage2.setScene(settingsScene);
stage2.show();
labelSettings.setOnMouseClicked(t->stage2.hide());
});
}
And there's another possibility: you can use Gluon Charm, to manage different views.
Have a look at this project to get you started.

Categories

Resources