Search code examples
javafxmodel-view-controllerscene

JavaFX change scene (view) in MVC


I have to do a game (Connect 4) as a project for my university, based on an MVC(Model, View, Controller) model. Now I am done with the two views (one which asks the user for input, the other that should print out the grid for the game, based on the user's input, but I have a problem, I cannot merge these two views and the two CSS documents together. Does anybody know how to do this? Thank you very much for your help!

import java.util.InputMismatchException;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Labeled;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;

public class View2 extends Application implements EventHandler<ActionEvent>{

   Stage window;

   //Boolean variable to store the answer
   static char number;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        window = primaryStage;

        //GridPane
        GridPane grid = new GridPane();
        grid.setPadding(new Insets(10, 10, 10, 10));
        grid.setVgap(8);
        grid.setHgap(10);

        //Row Label - Constraints use (child, column, row)
        Label rowLabel = new Label("Number of Rows:");
        GridPane.setConstraints(rowLabel, 0, 0);

        //Column Label
        Label colLabel = new Label("Number of Columns:");
        GridPane.setConstraints(colLabel, 0, 1);

        //Connections Label
        Label conLabel = new Label("Needed Connections:");
        GridPane.setConstraints(conLabel, 0, 2);

        //Rows Input
        TextField rowInput = new TextField();
        rowInput.setPromptText("Number Rows");
        GridPane.setConstraints(rowInput, 1, 0);

        //Column Input
        TextField colInput = new TextField();
        colInput.setPromptText("Number Columns");
        GridPane.setConstraints(colInput, 1, 1);

        //Needed Connections
        TextField conInput = new TextField();
        conInput.setPromptText("Needed Connections");
        GridPane.setConstraints(conInput, 1, 2);

        //Display customized grid
        Button displayButton = new Button("Display Grid");
        GridPane.setConstraints (displayButton, 1, 4);

        //Checking Input
       displayButton.setOnAction(e-> {
           isInt(rowInput, rowInput.getText());  
           isInt(colInput, colInput.getText());
           isInt(conInput, conInput.getText());           
       });

        //Add everything to grid
        grid.getChildren().addAll(rowLabel, colLabel, conLabel, rowInput, colInput, conInput, displayButton);

        Scene scene = new Scene(grid, 400, 200);
        scene.getStylesheets().add(getClass().getResource("styleView2.css").toExternalForm());
        window.setScene(scene);
        window.show();
    }

    //Check input
    private boolean isInt(TextField input, String message) {
        try {
            int number=Integer.parseInt(input.getText());
            input.setText("The input is valid");
            return true;
        } catch(NumberFormatException e) {

            input.setText("The input is not valid");
        }
        return false;
    }       
}
//CSS for View 
.root{
-fx-background-color: #383838;
-fx-font-size: 40pt;
}

.button{
-fx-background-color: linear-gradient(#86c1b9, #7cafc2);
-fx-background-radius: 15;
-fx-min-width: 120;
-fx-min-height: 120;
-fx-pref-width: 120;
-fx-pref-height: 120;

}  

//CSS for View2
.root{
    -fx-background-color: #F8F8F8;
    -fx-font-size: 10pt;
}

.label{
    -fx-text-fill: #181818;
}

.button{
    -fx-background-color: #AB4642;
    -fx-text-fill: #FFFFFF;
    -fx-background-radius: 5;
}


import java.util.ArrayList;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

//View for creating the grid
public class View {
        private Stage stage;
        private Model model;

        public int hRows = 6;
        public int vRows = 7;

        ArrayList[] hArray = new ArrayList[hRows];

        public View(Stage stage, Model model) {
            this.stage = stage;
            this.model = model;

                GridPane root = new GridPane();
                stage.setTitle("Connect 4");

                for (int i = 0; i < hArray.length; i ++) {
                    hArray[i] = new ArrayList<Button>();    
                }
                for (int i = 0; i < hArray.length; i ++) {
                    for(int j = 0; j < vRows; j ++ ) {
                        Button b = new Button();
                        hArray[i].add(b);   
                         b.setOnAction(this::gameButtons);      
                    }
                }

                for (int i = 0; i < hArray.length; i ++) {
                    for(int j = 0; j < vRows; j ++ ) {
                        root.add((Node) (hArray[i].get(j)), i, j);      
                    }
                }

                // Standard stuff for Scene and              Stage
                Scene scene = new Scene(root);


                scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());


                stage.setScene(scene);
                stage.show();
        }
        public void start() {
            stage.show();
        }

        private void gameButtons(ActionEvent e) {               
    }
}

Solution

  • When you need to learn something new, it is often much easier to do it on a smaller scale, rather than on you application.
    This goes in line with SO requirement of posting mre when asking or answering.
    Your question is essentially how to change scene in a javafx app, and the following code demonstrates just that, and nothing else. To test it you may copy the entire code into one file (View2.java) and run:

    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;
    
    public class View2 extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception {
    
            GridPane grid = new GridPane();
            grid.setPadding(new Insets(10, 10, 10, 10));
    
            Button displayButton = new Button("Display Grid");
            //Change scene
            displayButton.setOnAction(e-> {
                Model model = new Model(6,12);
                View view = new View(model);
                primaryStage.setScene(new Scene(view.getRoot()));
            });
    
            grid.getChildren().add(displayButton);
    
            Scene scene = new Scene(grid, 400, 200);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    class View{
    
        private final GridPane root;
    
        public View(Model model) {
    
            root = new GridPane();
    
            for (int i = 0; i < model.gethRows(); i ++) {
                for(int j = 0; j < model.getvRows(); j ++ ) {
                    Button b = new Button(i+"-"+j);
                    root.add(b, j, i);
                }
            }
        }
    
        GridPane getRoot() {
            return root;
        }
    }
    
    class Model {
    
        private final int hRows, vRows;
    
        Model(int hRows, int vRows) {
            this.hRows = hRows;
            this.vRows = vRows;
        }
    
        int gethRows() {
            return hRows;
        }
    
        int getvRows() {
            return vRows;
        }
    }