1

I am using Java FX (required for a class project), and I am struggling to format my MVC so that I can load multiple views onto the stage (various scenes). I have a Controller as seen below that has 2 instances of View1.

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.animation.AnimationTimer;

public class Controller extends Application {

public int page = 0;

private View1 view2;
private View1 view1;

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

@Override
public void start(Stage theStage) {
    view1 = new View1(theStage);
    view2 = new View1(theStage);
    new AnimationTimer() {
        public void handle(long currentNanoTime)
        {
            switch (page){
                case 0:
                    view1.update();
                    break;
                case 1:
                    view2.update();
                    break;
                default:
                    page = 0;
            }
            try {
                Thread.sleep(33);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }.start();
    theStage.show();
  }

}

The problem occurs at the line view2 = new View1(theStage);. Without this line, the output is a large canvas with a background image. With that line, however, there is no background image it is just a blank canvas. Below is my View I simplified it as much as possible, just one background image to determine if it's loaded correctly. (I left the imports out in order to keep it concise, if needed I can add them back in)

public class View1 {
Stage theStage;
Group root;
Scene theScene;
Canvas canvas;

// value of the height and width of screen
int canvasWidth = 1000;
int canvasHeight = 800; 

GraphicsContext gc;

Image background;

//View1 constructor initialize the starting position for the image
//Called in controller
public View1(Stage theStage) {


    this.theStage = theStage;
    this.theStage.setTitle("Estuary Game");

    root = new Group();
    theScene = new Scene(root);
    this.theStage.setScene(theScene);

    canvas = new Canvas(canvasWidth, canvasHeight);
    root.getChildren().add(canvas);
    gc = canvas.getGraphicsContext2D();

    background = createImage("assets/mini-game-1.png");
}

//Read image from file and return
private Image createImage(String image_file) {
    Image img = new Image(image_file);
    return img;
}

//method used to repaint on the image and called in controller
public void update() {
    // draw background and sharkMove such like current
    gc.drawImage(background, 0, 0);

}

}

I am not sure I am tackling the multiple views correctly, my intentions are to just have multiple scenes but I wasn't sure how to structure it.

1 Answer 1

1

Try the following structure (the following code is a one-file mre. Copy-paste it into SwitchScene.java and run) :

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class SwitchScene extends Application {

    public int page = 0;

    @Override
    public void start(Stage theStage) {

        new Controller(theStage);
        theStage.show();
    }

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

class Controller {

    private final View1 view1,  view2;
    private final Stage stage;

    private static final String[] images = {
            "https://findicons.com/files/icons/345/summer/128/cake.png",
            "http://icons.iconarchive.com/icons/atyourservice/service-categories/128/Sweets-icon.png"
    };

    Controller(Stage stage) {
        this.stage = stage;
        view1 = new View1(images[0]);
        view2 = new View1(images[1]);
        swapScenes();
    }

    void swapScenes(){

        new AnimationTimer() {

            int page = 2;
            @Override
            public void handle(long currentNanoTime){
                switch (page){
                    case 2:
                        page = 1;
                        stage.setScene(new Scene(new Group(view1)));
                        break;
                    case 1:
                        page = 2;
                        stage.setScene(new Scene(new Group(view2)));
                        break;
                }

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

class View1 extends ImageView {

    public View1(String imagePath) {
        super(imagePath);
    }
}

Edit: a version of View1 using canvas:

class View1 extends Group {

    public View1(String imagePath) {

        Image img = new Image(imagePath);
        Canvas canvas = new Canvas(img.getWidth(), img.getHeight());
        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.drawImage(img, 0, 0, canvas.getWidth(), canvas.getHeight());
        getChildren().add(canvas);
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much for responding. I feel like this is so close to what I need, however, in view I need to create a canvas and I need the variable gc (GraphicsContext) so I can populate the screen with a multitude of items. How can this be done without passing the stage or the scene to the view?
I am glad it helped. View1 can be any Node. Fpr example it can be a Group or Pane .You can have View1 extend Node and modify it to your needs.
I am getting an error that says Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: View2@7c69d5da[styleClass=root]is already set as root of another scene I think this could be because I keep instantiating a new scene but im not sure.
It is not clear in what context. Are you are trying to set the same root to two scenes ? For more help please post a new question and include an minimal reproducible example.
Thank you for all of the help, I marked the solution as correct since this is what I needed. The second image, however, is not showing up. It fluctuates between a blank screen and the first view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.