1

I'm fairly new to JavaFX and FXML. I've coded some java swing but that is a long time ago. To learn something new I'm creating a little board game but I can't seem to line up my GridPane with Rectangles inside it properly (The GridPane is inside a BorderPane). By that I mean (I believe) my GridPane is not binded properly. As you can see in my screenshot the GridPane doesn't move with the BorderPane when I resize the window.

These are my classes:

Main

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        BorderPane root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        Scene scene = new Scene(root, 800, 900);

        primaryStage.setTitle("Testing");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.toFront();
    }

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

Controller:

public class Controller implements Initializable {


    @FXML private GridPane gridBoard;
    @FXML private BorderPane borderPane;


    public void initialize(java.net.URL location,
                       java.util.ResourceBundle resources) {

        gridBoard.prefHeightProperty().bind(borderPane.heightProperty());
        gridBoard.prefWidthProperty().bind(borderPane.widthProperty());

    }

    public void fillBoardEvent(ActionEvent event) {

        for(int i = 0; i < 50; i++) {
            for(int j = 0; j < 50; j++) {
                InitiateCells n;

                // This is for creating the rectangles
                // and to give some specific cells 
                // different color
                if(i == 24) {
                    if(j == 19 || j == 20 || j == 21 || j == 22 || j == 23 || j == 24 || j == 25 || j == 26 || j == 27 ||
                        j == 28 || j == 29) {

                        n = new InitiateCells("" + i + "/" + j, 12, 12, i, j, 0);

                    } else {
                        n = new InitiateCells("" + i + "/" + j, 12, 12, i, j);
                    }
                } else {
                    n = new InitiateCells("" + i + "/" + j, 12, 12, i, j);
                }
            }
        }

    }

    public void exitEvent(ActionEvent event) {
        System.exit(0);
    }

    public class InitiateCells extends Rectangle {
        private String name;
        private double width;
        private double height;


        public InitiateCells(String name, double width, double height, int rowIndex, int columnIndex) {
            super(width, height);
            this.name = name;
            this.width = width;
            this.height = height;

            setFill(Color.web("#282828"));
            setStroke(Color.web("#3b3b3b"));
            setStrokeType(StrokeType.OUTSIDE);
            setStrokeWidth(2.0);


            gridBoard.add(this, columnIndex, rowIndex);

    }


        public InitiateCells(String name, double width, double height, int rowIndex, int columnIndex, int value) {
            super(width, height);
            this.name = name;
            this.width = width;
            this.height = height;

            setFill(Color.web("#282828"));
            setStroke(Color.web("#3b3b3b"));
            setStrokeType(StrokeType.OUTSIDE);
            setStrokeWidth(2.0);


            gridBoard.add(this, columnIndex, rowIndex);
    }

Sample.fxml

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0"
        prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
        fx:controller="sample.Controller" fx:id="borderPane">


    <center>
        <GridPane prefHeight="770.0" prefWidth="800.0" BorderPane.alignment="CENTER" fx:id="gridBoard" >
            <children>

            </children>
        </GridPane>
    </center>

    <top>
        <VBox prefHeight="30.0" prefWidth="800.0" BorderPane.alignment="TOP_CENTER">
            <children>
                <MenuBar>
                    <menus>
                        <Menu text="File">
                            <items>
                                <MenuItem text="New Game" onAction="#fillBoardEvent"/>
                                <MenuItem text="Save as GIF"/>
                                <MenuItem text="Export statistics"/>
                                <MenuItem text="Exit" onAction="#exitEvent"/>
                            </items>
                        </Menu>
                        <Menu text="Help">
                            <items>
                                <MenuItem text="Game of Life"/>
                                <MenuItem text="How to play"/>
                                <MenuItem text="Open Javadoc"/>
                            </items>
                        </Menu>
                        <Menu text="About">
                            <MenuItem text="Game of Life"/>
                            <MenuItem text="How to play"/>
                            <MenuItem text="Open Javadoc"/>
                        </Menu>
                    </menus>
                </MenuBar>
            </children>
        </VBox>
    </top>

    <bottom>
        <VBox prefHeight="70.0" prefWidth="800.0" BorderPane.alignment="BOTTOM_CENTER">
            <children>
                <ProgressBar prefHeight="70.0" prefWidth="800.0" progress="50.0" />
            </children>
        </VBox>
    </bottom>
</BorderPane>

This is the problem; When I try to resize the window, my GridPane and VBox stays in the same place. It should go from edge to edge when I resize the window. This is how it looks: Board

Matthias
  • 3,582
  • 2
  • 30
  • 41
patski
  • 329
  • 6
  • 15
  • Can you clarify what you want to happen when you increase the size of the window? Currently (by default), the columns and rows in the grid stay the same size because they will size themselves to be just big enough to hold their content. You can fairly easily change that with column constraints and row constraints objects; however the rectangles have fixed sizes so you will introduce gaps between them. What behavior are you actually looking for here? – James_D Feb 04 '16 at 18:47
  • I want the rectangles to resize automatically with the window whenever its being resized (same with the GridPane). But you're saying that it's not possible without introducing gaps? – patski Feb 04 '16 at 18:52
  • 1
    Well, anything's possible :). But I would not use `Rectangle`s here, I would use something resizable (such as a `Region`). Let me put together an answer... – James_D Feb 04 '16 at 18:55
  • @patski Please do not remove the question from the site. I rolled back your edit. The question should also help others who have a similar problem. – Matthias Feb 06 '16 at 09:00
  • @Matthias Oh, sorry about that! – patski Feb 06 '16 at 09:03

1 Answers1

3

The problem is not that the grid pane is not resizing: the problem is that when the grid pane resizes, the columns and rows do not resize. Hence the grid pane has lots of blank space after the horizontal space taken up by the columns and after the vertical space taken up by the rows. (This also explains why it's not appearing centered: the grid pane itself is centered in the border pane, but the rows and columns appear in the top left of the grid pane itself.)

You can fix this easily enough by setting the column constraints and row constraints on the grid pane:

public void fillBoardEvent(ActionEvent event) {

    int numRows = 50 ;
    int numColumns = 50 ;

    for (int i = 0 ; i < numRows; i++) {
        RowConstraints row = new RowConstraints();
        row.setVgrow(Priority.ALWAYS);
        gridBoard.getRowConstraints().add(row);
    }

    for (int j = 0 ; j < numColumns; j++) {
        ColumnConstraints col = new ColumnConstraints();
        col.setHgrow(Priority.ALWAYS);
        gridBoard.getColumnConstraints().add(col);            
    }

    for(int i = 0; i < numRows; i++) {
        for(int j = 0; j < numColumns; j++) {
            InitiateCells n;

            // code as before...
        }
    }
}

Now the columns and rows will grow, but their content will not. So you end up with space between the cells like this:

enter image description here

You can't really fix this easily using Rectangles, because Rectangles are not resizable, and so whatever settings you put on the grid pane, it won't be able to resize the rectangles for you. (You could introduce bindings between the grid pane's size and the rectangles width and height, but that will get very ugly very fast.) I would use Regions instead of Rectangles, as Regions are resizable. Note that the values you assign as the width and height of the cells are really preferred width and height, since you want them to resize with the window.

A Region does not have fill, stroke etc, but it can by styled via CSS, so I would do

public class InitiateCells extends Region {
    private String name;
    private double width;
    private double height;


    public InitiateCells(String name, double width, double height, int rowIndex, int columnIndex) {
        this.name = name;
        this.width = width;
        this.height = height;

        setPrefSize(width, height);
        getStyleClass().add("board-cell");

        gridBoard.add(this, columnIndex, rowIndex);

    }


    public InitiateCells(String name, double width, double height, int rowIndex, int columnIndex, int value) {
        this(name, width, height, rowIndex, columnIndex);
        pseudoClassStateUpdated(PseudoClass.getPseudoClass("on"), true);
    }

}

Now in your main class, add an external stylesheet:

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

and add a board-style.css file with

.board-cell {
    -fx-background-color: #3b3b3b, #282828 ;
    -fx-background-insets: 0, 2 ;
}

.board-cell:on {
    -fx-background-color: #3b3b3b, white ;
    -fx-background-insets: 0, 2 ;   
}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • 1
    Wow, I did not expect this kind of answer when I posted the question. Thank you so much for taking the time to, not only give me a better solution, but also for taking the time to tell me why this is a better solution with examples. Thank you :) – patski Feb 04 '16 at 19:33