Javafx create rectangles in a loop - java

I am learning Javafx and am having trouble getting my for loop to create a new rectangle on each iteration. When I run the program it creates one rectangle at the top left position and that is it. My goal is to create a grid of rectangles based on the amount of columns, rows, pixels wide, and pixels tall specified. Everything is tested to work besides the creation of rectangles.
for(int i = 0; i < columns; ++i)
{//Iterate through columns
for(int j = 0; j < rows; ++j)
{//Iterate through rows
Color choice = chooseColor(rectColors);
//Method that chooses a color
rect = new Rectangle(horizontal*j, vertical*i, horizontal, vertical);
//Create a new rectangle(PosY,PosX,width,height)
rect.setStroke(choice);
//Give rectangles an outline so I can see rectangles
root.getChildren().add(rect);
//Add Rectangle to board
}
}
I am trying to figure out why the rectangles aren't being created. Any help would be greatly appreciated.

I used the same program which you had.
Try with this and check where you made the mistake. Also check the values you initialized.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class RectangleDemo extends Application{
#Override
public void start(Stage stage) {
AnchorPane root = new AnchorPane();
Scene scene = new Scene(root);
stage.setScene(scene);
int columns = 20, rows = 10 , horizontal = 20, vertical = 20;
Rectangle rect = null;
for(int i = 0; i < columns; ++i)
{//Iterate through columns
for(int j = 0; j < rows; ++j)
{//Iterate through rows
// Color choice = chooseColor(rectColors);
//Method that chooses a color
rect = new Rectangle(horizontal*j, vertical*i, horizontal, vertical);
//Create a new rectangle(PosY,PosX,width,height)
rect.setStroke(Color.RED);
//Give rectangles an outline so I can see rectangles
root.getChildren().add(rect);
//Add Rectangle to board
}
}
scene.setRoot(root);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I hope it will help you...

Related

Why do the node positions in my gridpane affect the layout of my grid?

I'm trying to recreate the "snake" game using GridPane in JavaFX. My code seems to run properly except for this specific error, where anytime I use my keys to traverse the green node (titled head) toward the yellow node (titled food), the rows or columns of the grid seem to shorten by one unit, causing the grid to collapse in some manner. Is there a way to stop the GridPane from resizing? Below is my code:
package snake;
import java.util.ArrayList;
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class snakemain extends Application {
Random random = new Random();
int posX = random.nextInt(21), posY = random.nextInt(21), foodposX = random.nextInt(24), foodposY = random.nextInt(24);
public static void main(String... args) {
launch(args);
}
public void start(Stage stage) {
//Creates Scene and stage setting + gridpane
stage.setTitle("Snake by Yeldor");
GridPane gridpane = new GridPane();
Random random = new Random();
Scene scene = new Scene(gridpane, 500, 500);
scene.setFill(Color.WHITE);
gridpane.setGridLinesVisible(true);
gridpane.setHgap(20);
gridpane.setVgap(20);
//creates head of snake, Arraylist of snakes body parts, and food consumable for snake
ArrayList<Rectangle> snakeBody = new ArrayList<Rectangle>();
Rectangle head = new Rectangle(20,20,Color.GREEN.brighter().brighter());
//invisible block to manage grid
Rectangle food = new Rectangle(20,20, Color.YELLOW.brighter().brighter());
//adds rectangles to grippane
gridpane.add(head, posX, posY);
gridpane.add(food, foodposX, foodposY);
//makes food non mangaged by the gridpane
scene.setOnKeyPressed(e ->
{
String s = e.getCode().toString();
try {
switch(s) {
case "W": gridpane.getChildren().remove(head);
gridpane.add(head, posX, --posY);
break;
case "A": gridpane.getChildren().remove(head);
gridpane.add(head, --posX, posY);
break;
case "S": gridpane.getChildren().remove(head);
gridpane.add(head, posX, ++posY);
break;
case "D": gridpane.getChildren().remove(head);
gridpane.add(head, ++posX, posY);
break;
}
if (posX == 24 || posY == 24 || posX == -1 || posY == -1) {
missionFailed();
stage.close();
}
}
catch(IllegalArgumentException error) {
missionFailed();
stage.close();
}
});
stage.setScene(scene);
stage.show();
}
void missionFailed() {
Stage failedPopup = new Stage();
failedPopup.setTitle("You Died!");
failedPopup.initModality(Modality.APPLICATION_MODAL);
Button OK = new Button("OK");
Group group = new Group();
Scene miniScene = new Scene(group, 150, 100);
group.getChildren().add(OK);
failedPopup.setScene(miniScene);
failedPopup.show();
OK.setOnMouseClicked(q -> {
failedPopup.close();
});
}
}
Using hgap and vgap does not modify the column size, it modifies the space between columns. If you e.g. place the Rectangles next to each other horizontally (same row index, column index differing by 1), the distance between both nodes is vgap; there are exactly 2 columns that are filled and have a width != 0. Now move the Rectangles to the same cell and only a single column with a width != 0 leading to unexpected results.
Instead you should restrict the size of the rows/columns:
// gridpane.setHgap(20);
// gridpane.setVgap(20);
int rows = 500 / 20;
int columns = 500 / 20;
RowConstraints rConstraints = new RowConstraints(20);
ColumnConstraints cConstraints = new ColumnConstraints(20);
for (int i = 0; i < columns; i++) {
gridpane.getColumnConstraints().add(cConstraints);
}
for (int i = 0; i < rows; i++) {
gridpane.getRowConstraints().add(rConstraints);
}
Another Solution that worked for me was to fill up the whole Area with transparent Rectangulars and just set the color of the Rectangulars used at the moment.

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.
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);
}
}
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.

new line when i display 10 ellipse

I am new in processing and java, I have some exercise to display 100 ellipses but the screen size is (900, 600), and I want break 100 in 10 lines of 10, but I don't know how to break line in processing , I already use translate(https://processing.org/reference/translate_.html),but it doesn't work.
//function
void draw(){
smooth();
noStroke();
fill(23,43,208,200);// cor azul
ellipse(posX,posY,12,10);
noStroke();
fill(242,76,39);//cor vermelho
ellipse(posX,posY,12,10);
}
for (int i=1; i<ellipses.length; i++)
{
for (int j=i; j<ellipses.length; j++)
{
if(j%10==0)
ellipses[i].draw();//calling function
}
}
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;
public class T15DrawEllipses extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Group group = new Group();
Scene scene = new Scene(group, 900, 600);
for (int row = 0; row < 10; row++) {
for (int col = 0; col < 10; col++) {
Ellipse e = new Ellipse();
e.setCenterX(44 + col * 90);
e.setCenterY(29 + row * 60);
e.setRadiusX(45);
e.setRadiusY(30);
group.getChildren().add(e);
}
}
primaryStage.setScene(scene);
primaryStage.show();
}
}
A complete example of 10 rows/columns with ellipses.
The best thing you can do when you have questions like this is to get out a piece of graph paper, and draw out a bunch of examples until you notice a pattern. What is the X,Y position of every cirlce you want to draw? What is the X value of the first row, the second row, the third row? What is the Y value of the first column, the second column, the third column?
You should also get into the habit of breaking your problem down into smaller pieces and taking those pieces on one at a time. For example, instead of trying to draw 100 circles in a grid, why don't you just try to draw 10 circles in a single row? Create a function that draws a row of circles. Then try calling that function multiple times to create your grid of circles.
If you get stuck on a specific step, you can ask a more specific question along with a MCVE. Good luck.

Why won't anything show up in my JavaFX application?

I am currently trying to make an 8x8 board and cannot seem to figure out why my rectangle objects are not showing. I am trying to figure out the logic behind one row before I do it multiple times to get the whole board. Below is my current code:
import javafx.application.*;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Board extends Application {
public static void main(String[] args) {
launch();
}
public void start(Stage ps) {
TilePane tp = new TilePane();
Pane p = new Pane();
for (int column = 0; column > 8; column++) {
// This loop is used to determine the center of the rectangle
for (int x = 10; x < 160; x += 20) {
Rectangle r = new Rectangle();
r.setWidth(20);
r.setHeight(20);
r.setX(x);
r.setY(10);
if (column == 0 || column % 2 == 0) {
r.setFill(Color.BLACK);
}
else {
r.setFill(Color.GREY);
}
tp.getChildren().add(r);
}
}
p.getChildren().add(tp);
Scene s = new Scene(p, 160, 160);
ps.setScene(s);
ps.setTitle("PP2 Halma Project");
ps.show();
}
}
for (int column = 0; column > 8; column++) - This will never happen because 0 can never be more than 8.
r.setX(x) - I don't think you would need this. You should let TilePane layout the rectangles for you; you just need to define a size for it.
Pane p = new Pane() - Personally, I think this is redundant. Using just TilePane without it will work just fine. This will not cause your program to bug, though.

GridLayout stacks all JPanels on first cell

I am trying to create a map for a game I am making with a JPanel that uses gridLayout. In my first tests I use a 5x5 grid and create my small panels which are a subclass of JPanel. My program creates them fine but when I add all of the panels into the larger panel and display it, only the first square shows up and the rest is blank. Why does it do that?
Here is my code for the MapSpace(smaller panel):
import javax.swing.*;
import java.awt.*;
public class MapSpace extends JPanel{
private int ownerTag;
private int xPos, yPos;
public MapSpace(){
xPos = 0;
yPos = 0;
ownerTag = 0;
setBackground(Color.WHITE);
}
public MapSpace(MapSpace m){
xPos = m.getX();
yPos = m.getY();
ownerTag = m.getID();
setBackground(m.getColor());
}
and here is my code for the Map:
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class Map extends JPanel{
private int cols, rows;
private int randCol, randRow;
private MapSpace[][] spaces;
Random gen = new Random();
public Map(int w, int h){
cols = h;
rows = w;
setLayout(new GridLayout(cols, rows));
setBackground(Color.WHITE);
spaces = new MapSpace[cols][rows];
for(int i = 0; i < cols; i++){
for(int j = 0; j < rows; j++){
MapSpace panel = new MapSpace(i, j);
spaces[i][j] = panel;
}
}
assignSpaces(3);
setColors();
for(int i = 0; i < cols; i++){
for(int j = 0; j < rows; j++){
MapSpace spot = new MapSpace(spaces[i][j]);
add(spot);
}
}
setSize(400, 400);
}
the second nested for loop is where all the mapSpaces are added but when I put the map in a JFrame and display it in a GUI window only one small square in the top left corner appears.
Why are you trying to create a MapSpace with an instance of MapSpace?
Just create the MapSpace with the parameters you want and then add the MapSpace to your Array and the panel at the same time.
and display it in a GUI window only one small square in the top left corner appears.
Probably because you don't give a preferredSize() size to your MapSpace class so it defaults to (10, 10) which is the size for a panel using a FlowLayout with no components added to it. So since you create a 5x5 grid you probably see a (50, 50) white square.
Override the getPreferredSize() of your MapSpace class to return the default Dimension for each square.

Categories