I am working on an exercise that is asking me to do the following;
Create a GridPane
Set the pane’s horizontal and vertical gap to zero
Set the pane’s grid line visibility to true
Use nested FOR loops to create and add buttons to the pane (loops
starts from 0 to 10)
Each button must be labeled with any number between 0 to 99
Color the buttons based on the following rules:
a. If the color’s label is divisible by 2, then change the color to Blue
b. If the color’s label is divisible by 3, then change the color to
Yellow
c. If the color’s label is divisible by 6, then change the color to Green
Add the pane to a scene
Add the scene to a stage, then display the Stage
I have everything set up, just not sure how to read the value generated by Math.random and do assign a specific color to that button.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
public class Exercise8GridPane extends Application {
#Override
public void start(Stage primary) {
primary.setTitle("Exercise 8");
GridPane gp = new GridPane();
gp.setHgap(0);
gp.setVgap(0);
gp.setGridLinesVisible(true);
for (int k = 0; k < 10; k++) {
for (int l = 0; l < 10; l++) {
Button btn = new Button(String.valueOf((int)(Math.random() * 100)));
// if / 3 == 0){
btn.setStyle("-fx-base:red;-fx-text-fill:yellow");
gp.add(btn, l, k);
}
}
Scene s = new Scene(gp);
primary.setScene(s);
primary.show();
}
public static void main(String[] args) {
launch(args);
}
}
The java.lang.Math.random() returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else.
There are countless ways to read it.
I would recommend doing something like
int RED = (int) (Math.random() * 256);
// Note that Math.random() returns a value less than 1.0
int BLUE = ...
It's difficult to get three values from one number, so I think this will work well.
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.
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.
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...
This is my first program written in JavaFX (as opposed to Swing). I'm starting small by simply displaying data sets in a matrix of buttons (I do not wish to use a Table just yet).
package matrixjavafx;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.util.Random; // required for random number generation
/**
*
* #author Matt
*/
public class MatrixJavaFX extends Application {
Button[][] matrix; //names the grid of buttons
#Override
public void start(Stage primaryStage) {
int SIZE = 10;
int length = SIZE;
int width = SIZE;
StackPane root = new StackPane();
matrix = new Button[width][length]; // allocates the size of the matrix
// runs a for loop and an embedded for loop to create buttons to fill the size of the matrix
// these buttons are then added to the matrix
for(int y = 0; y < length; y++)
{
for(int x = 0; x < width; x++)
{
Random rand = new Random(); // Creates new Random object for generating random numbers
// The following variables are generated using Random object rand.
// rand.nextInt(2) generates a double ranging from 0.000 to 0.999.
// setting the target variable to be an integer truncates the range to 0 - 1.
int rand1 = rand.nextInt(2); // Declare and initialize random integer (0 - 1) + 1
matrix[x][y] = new Button(/*"(" + rand1 + ")"*/); //creates new random binary button
matrix[x][y].setText("(" + rand1 + ")"); // Sets the text inside the matrix
matrix[x][y].setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Random Binary Matrix (JavaFX)");
}
});
root.getChildren().add(matrix[x][y]);
}
}
Scene scene = new Scene(root, 500, 500);
primaryStage.setTitle("Random Binary Matrix (JavaFX)");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
greeting(); // Greets the User and explains the purpose of the program
launch(args); // Opens the window that generates and displays the matrix
//new MatrixSwingGUI(width, length); // makes new MatrixSwing with 2 parameters
thanks(); // Thanks User and indicates that the program is about to close
}
public static void greeting()
{
// Greets the User and displays the program's purpose
System.out.println("Welcome to the Random Matrix Generator\n");
System.out.println("The purpose of this program is to generate and display "
+ "\na 10 x 10 matrix of random 0's, and 1's.");
}
public static void thanks() // Thanks User and indicates that the program is about to close
{
System.out.println("\nGoodbye and Thank You for using the Random Matrix Generator\n\n");
} // End thanks method
}
The heart of the problem seems to be the following line, since by default all of the buttons are stacking on top of each other in the center of the pane.
StackPane root = new StackPane();
That said, I would like the buttons to align side by side for all of length and width, resulting in an n x m matrix. What should be done to accomplish this? What additional javafx.scene.* files need to be imported?
The basic problem is the Layout that you have chosen for the project. You can get an in-depth knowledge about layouts, that javafx support over here
StackPane stacks all the Nodes that you pass it. I would suggest you to use GridPane inplace of StackPane.
GridPane root = new GridPane();
To add the nodes, use
root.add(matrix[x][y], y, x);
P.S. I would also advice you to rename your buttons, to give you more clarity on button representing row's and column's of the matrix. You can use something as, though its totally optional ! :)
matrix[x][y].setText(x + "," + y);