Thomas Linssen
Thomas Linssen

Reputation: 129

Display a 2D grid of images or shapes in java

I made a 2D grid of ASCII characters before in which i was able to move an ascii character around. Now i want to take it to the next level by making a "visualised" version of it in a javafx window. I have tried making 2 image objects, one with a black square inside of it, and one with a white one and then putting those 2 objects multiple times inside a 2D grid like this:

  Image[][] Grid = {
  {B,W,B,B,B,B,B,B,B,B,B},
  {B,B,B,B,W,W,W,B,B,B,B},
  {B,B,B,B,B,B,B,B,B,B,B}
  };

The problem is that the only way i know how to display them, is by making an imageview object for each index and if i were to say, want a 25X25 grid, that would mean i would have to make 625 imageview objects which would obviously be ridiculous.

I also tried simply putting the grid indexes one by one into the pane like this:

HBox gameLayout = new HBox(Grid[1][1], Grid[1][2], Grid[1][3]);

but that gives me a "invocationTargetException".

My goal is to be able to make snake by specifically targeting and manipulating grid elements. I want the square-color/imageView/rectangle/whatever to change when i change the value of a "B"array element to "W" (white) but the things i'v tried are either very inefficient or just don't work.

Upvotes: 0

Views: 2713

Answers (1)

James_D
James_D

Reputation: 209235

It's not at all clear what your objection is to creating multiple ImageViews. Since they can refer to the same Image instance, this should be fairly efficient (the image data doesn't need to be replicated).

This seems to work just fine:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class TiledBoard extends Application {

    private final int tileSize = 30 ;

    @Override
    public void start(Stage primaryStage) {

        Image b = createImage(Color.BLACK);
        Image w = createImage(Color.WHITE);


        Image[][] grid = {
            {b,w,b,b,b,b,b,b,b,b,b},
            {b,b,b,b,w,w,w,b,b,b,b},
            {b,b,b,b,b,b,b,b,b,b,b}
        };

        GridPane gridPane = new GridPane();

        // for visualizing the different squares:
        gridPane.setHgap(2);
        gridPane.setVgap(2);
        gridPane.setStyle("-fx-background-color: grey;");

        for (int y = 0 ; y < grid.length ; y++) {
            for (int x = 0 ; x < grid[y].length ; x++) {
                ImageView imageView = new ImageView(grid[y][x]);
                imageView.setFitWidth(tileSize);
                imageView.setFitHeight(tileSize);
                gridPane.add(imageView, x, y);
            }
        }
        Scene scene = new Scene(gridPane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Image createImage(Color color) {
        WritableImage image = new WritableImage(1, 1);
        image.getPixelWriter().setColor(0, 0, color);
        return image ;
    }

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

enter image description here

You could do this with some kind of Shape (e.g. Rectangle), if you prefer:

@Override
public void start(Stage primaryStage) {

    Color b = Color.BLACK;
    Color w = Color.WHITE;


    Color[][] grid = {
        {b,w,b,b,b,b,b,b,b,b,b},
        {b,b,b,b,w,w,w,b,b,b,b},
        {b,b,b,b,b,b,b,b,b,b,b}
    };

    GridPane gridPane = new GridPane();

    // for visualizing the different squares:
    gridPane.setHgap(2);
    gridPane.setVgap(2);
    gridPane.setStyle("-fx-background-color: grey;");

    for (int y = 0 ; y < grid.length ; y++) {
        for (int x = 0 ; x < grid[y].length ; x++) {
            Rectangle rect = new Rectangle(tileSize, tileSize, grid[y][x]);
            gridPane.add(rect, x, y);
        }
    }
    Scene scene = new Scene(gridPane);
    primaryStage.setScene(scene);
    primaryStage.show();
}

or with a Region:

@Override
public void start(Stage primaryStage) {

    Color b = Color.BLACK;
    Color w = Color.WHITE;


    Color[][] grid = {
        {b,w,b,b,b,b,b,b,b,b,b},
        {b,b,b,b,w,w,w,b,b,b,b},
        {b,b,b,b,b,b,b,b,b,b,b}
    };

    GridPane gridPane = new GridPane();

    // for visualizing the different squares:
    gridPane.setHgap(2);
    gridPane.setVgap(2);
    gridPane.setStyle("-fx-background-color: grey;");

    for (int y = 0 ; y < grid.length ; y++) {
        for (int x = 0 ; x < grid[y].length ; x++) {
            Region rect = new Region();
            rect.setMinSize(tileSize, tileSize);
            rect.setPrefSize(tileSize, tileSize);
            rect.setMaxSize(tileSize, tileSize);
            rect.setBackground(new Background(new BackgroundFill(grid[y][x], CornerRadii.EMPTY, Insets.EMPTY)));
            gridPane.add(rect, x, y);
        }
    }
    Scene scene = new Scene(gridPane);
    primaryStage.setScene(scene);
    primaryStage.show();
}

Which of these is better really just depends on what else you want to do with them.

Upvotes: 2

Related Questions