简体   繁体   中英

how to change scene based on time in javafx

New to java and JavaFX so please bear with me

I need to do a presentation of 5 3d fruit models that show in a continuous loop, 15 seconds apart: fruit1 for 15 seconds then fruit2 for 15 seconds ad so on and so forth.. until fruit5 for 15 seconds and then back to fruit1 and continues until I hit the ESC key which should close the window.

I also understand that it's ideal to change the root group object that makes up the scene instead of changing the scene, so I changed that in my code

I understand that a timeline is needed in order to change something in the scene as it plays out, but I've tried with something similar to what this answer says but I don't get the logic of how to switch the root of the scene every 15seconds

UPDATE:

I gave up on the timeline option and I found the platform.run option as seen on this article which seems to work as I see the window updates iterating from the first fruit in the scenes array to second one but I'm not sure why it only runs once when I need it to run every 15 seconds which means that my scene switcher: nextSceneIndex() should go back and forth between 1 and 0.

UPDATE2:

I went back to the timeline suggestion and I implemented Sedrick's solution and it worked... I can't be happier:)

Here's my working code!


  public void start(Stage stage) throws Exception {

        BorderPane[] scenes = new BorderPane[]{createSceneApple(),createSceneCarrot(),createSceneTomato()};


        Timeline tl = new Timeline();
        tl.setCycleCount(Animation.INDEFINITE);
        KeyFrame kf_fruit = new KeyFrame(Duration.seconds(10),
                new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent event) {

                       if (index==0){
                           root.getChildren().setAll(scenes[0]);
                           index = 1;
                       }else if(index==1){
                           root.getChildren().setAll(scenes[1]);
                           index = 2;
                       }else if(index==2){
                           root.getChildren().setAll(scenes[2]);
                           index = 0;
                       }
                    }  
        });

        tl.getKeyFrames().add(kf_fruit);
        tl.play();

        Scene scene = new Scene(root, windowWidth, windowHeight);
        stage.setScene(scene);
        stage.show();

}


Maybe you can get some ideas from here. This uses the code from the link I posted above. Timeline is used to loop through a list of Shape and info about that shape.

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * JavaFX App
 */
public class App extends Application {

    @Override
    public void start(Stage stage) {
        List<MyShape> shapes = new ArrayList();
        shapes.add(new MyShape("Circle", "Shape.Circle", "More Circle Info", new Circle(25, Color.BLUE)));
        shapes.add(new MyShape("Rectangle", "Shape.Rectangle", "More Rectangle Info", new Rectangle(100, 50, Color.RED)));
        shapes.add(new MyShape("Line", "Shape.Line", "More Line Info", new Line(0, 0, 100, 100)));


        TextField tf1 = new TextField();
        TextField tf2 = new TextField();
        TextArea ta1 = new TextArea();        
        VBox leftWindow = new VBox(tf1, tf2, ta1);

        StackPane rightWindow = new StackPane(shapes.get(1).getShape());

        AtomicInteger counter = new AtomicInteger();
        Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println(counter.get() % shapes.size());
                MyShape currentShape = shapes.get(counter.getAndIncrement() % shapes.size());
                tf1.setText(currentShape.getName());
                tf2.setText(currentShape.getType());
                ta1.setText(currentShape.getMoreInfo());
                rightWindow.getChildren().set(0, currentShape.getShape());
            }
        }));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();

        BorderPane root = new BorderPane();
        root.setLeft(new StackPane(leftWindow));
        root.setRight(rightWindow);

        var scene = new Scene(root, 640, 480);
        stage.setScene(scene);
        stage.show();
    }

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

}

Update: If you only have two scenes, that simplifies some things. You basically need to set the initial view. You then need to switch out the view currently showing every two seconds. (I used two seconds so that you can see the views before they are switched out). I created my own version of createSceneCarrot and createSceneApple since I don't know your implementation.

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * JavaFX App
 */
public class App extends Application {

    @Override
    public void start(Stage stage) {
        BorderPane[] scenes = new BorderPane[]{createSceneApple(),createSceneCarrot()};


        StackPane root = new StackPane(scenes[0]);//Set initial view;      

        Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(2), (ActionEvent event) -> {
            if(root.getChildren().get(0).equals(scenes[0]))//If the first scene is loaded, load the second scene.
            {
                root.getChildren().set(0, scenes[1]);
            }
            else
            {
                root.getChildren().set(0, scenes[0]);
            }
        }));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();

        var scene = new Scene(root, 640, 640);
        stage.setScene(scene);
        stage.show();
    }

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

    public BorderPane createSceneApple()
    {
        BorderPane borderPane = new BorderPane();

        TextField tf1 = new TextField("Rectangle 1");
        TextField tf2 = new TextField("Rectangle Color: Blue");
        TextArea ta1 = new TextArea("20x40");        
        VBox leftWindow = new VBox(tf1, tf2, ta1);
        borderPane.setLeft(leftWindow);

        StackPane rightWindow = new StackPane(new Rectangle(20, 40, Color.BLUE));
        borderPane.setRight(rightWindow);

        return  borderPane;
    }

    public BorderPane createSceneCarrot()
    {
        BorderPane borderPane = new BorderPane();

        TextField tf1 = new TextField("Circle 1");
        TextField tf2 = new TextField("Circle Color: Blue");
        TextArea ta1 = new TextArea("Radius: 50");        
        VBox leftWindow = new VBox(tf1, tf2, ta1);
        borderPane.setLeft(leftWindow);

        StackPane rightWindow = new StackPane(new Circle(50, Color.RED));
        borderPane.setRight(rightWindow);

        return  borderPane;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM