JavaFX Rectangles inside FlowPane - javafx

I have a problem to draw this image (below link) I had his in the middle of flow pane but only half of this! How to draw full image>?
http://s16.postimg.org/lrus832dx/Capture2.png
http://s27.postimg.org/hsujjp1s3/Capture1.png

Ok, I think I understand your problem now. I suggest you to use a GridPane instead, then you can do it this way:
#Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
int rows = 2;
int columns = 2;
int rectangleWidth = 50;
int rectangleHeight = 50;
root.setMaxSize(rectangleWidth*columns, rectangleHeight*rows);
for(int row = 0; row < rows; row++)
{
for(int col= 0; col< columns; col++)
{
Rectangle rectangle = new Rectangle(rectangleWidth, rectangleHeight);
root.add(rectangle, col, row);
if(row % 2 == 0)
{
rectangle.setFill(col % 2 == 0 ? Color.ORANGE : Color.BLACK);
}
else
{
rectangle.setFill(col % 2 != 0 ? Color.ORANGE : Color.BLACK);
}
}
}
Scene scene = new Scene(new StackPane(root), 700, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
We need to wrap the GridPane containing the Rectangles in a StackPane to center it in its parent.

Related

Clearing past drawings on javafx using timeline

I am trying to make a snake game using maven project on JavaFX. In my code snake was moving but the previous coordinates are not cleared on the scene. Are there any solution for this? Here is my code:
public class Main extends Application {
int sceneX = 600;
int sceneY = 400;
ArrayList <Point> snake = new ArrayList<>();
private GraphicsContext gc;
private void run(GraphicsContext gc) {
drawSnake(gc);
for (int i = snake.size()-1; i>=1; i--) {
snake.get(i).x = snake.get(i - 1).x;
snake.get(i).y = snake.get(i - 1).y;
}
snake.get(0).x++;
}
private void drawSnake(GraphicsContext gc) {
for (int i =0; i<3; i++) {
gc.fillRoundRect(snake.get(i).getX(), snake.get(i).getY(),5,5,3,3);
}
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("SNAKE");
Group root = new Group();
Canvas canvas = new Canvas(sceneX, sceneY);
root.getChildren().add(canvas);
Scene scene = new Scene (root);
primaryStage.setScene(scene);
primaryStage.show();
gc = canvas.getGraphicsContext2D();
for (int i = 0; i<3; i++) {
snake.add(new Point(300, 300));
}
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(130), e -> run(gc)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
I agree with what #jewelsea mentioned in the comments.
If you don't have very complex drawings/painting on the canvas, I think using scenegraph approach should make things simple.
If you opt for canvas, one possible drawback I can think of is : you need to redraw the entire canvas. Because clearing only part of the rectangle will not be a solution if you have some layered drawings (like background.. etc)
private void run(GraphicsContext gc) {
for (int i = 0; i < snake.size(); i++) {
gc.clearRect(snake.get(i).x, snake.get(i).y, size, size);
}
int lastIndex = snake.size() - 1;
for (int i = 0; i < lastIndex; i++) {
snake.get(i).x = snake.get(i + 1).x;
}
snake.get(lastIndex).x += size;
drawSnake(gc);
}
In the below gif for canvas approach, clearing the snake alone is not sufficient if I have some background.
On the other hand, if I use scenegraph approach, once we include the building blocks of the snake, all we need to do is to update the position of the building blocks.
private void run() {
int lastIndex = shapes.size() - 1;
for (int i = 0; i < lastIndex; i++) {
shapes.get(i).setLayoutX(shapes.get(i + 1).getLayoutX());
}
shapes.get(lastIndex).setLayoutX(shapes.get(lastIndex).getLayoutX() + size);
}
Below is the complete demo differentiating the two approaches:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
public class SnakeGameDemo extends Application {
int width = 300;
int height = 200;
int startX = 100;
int startY = 100;
int size = 5;
int speed = 250;
List<Point> snake = new ArrayList<>();
List<Rectangle> shapes = new ArrayList<>();
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("SNAKE");
GridPane root = new GridPane();
root.setPadding(new Insets(10));
root.setHgap(10);
root.setVgap(10);
root.addRow(0, new Label("Canvas"), new Label("SceneGraph"));
root.addRow(1, canvasApproach(), scenegraphApproach());
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
private Node canvasApproach() {
Canvas canvas = new Canvas(width, height);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.RED);
gc.fillRoundRect(0, 0, width, height, 0, 0);
gc.setFill(Color.GREEN);
for (int i = 0; i < 3; i++) {
snake.add(new Point(startX + (i * size), startY));
}
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(speed), e -> run(gc)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
return canvas;
}
private void run(GraphicsContext gc) {
for (int i = 0; i < snake.size(); i++) {
gc.clearRect(snake.get(i).x, snake.get(i).y, size, size);
}
int lastIndex = snake.size() - 1;
for (int i = 0; i < lastIndex; i++) {
snake.get(i).x = snake.get(i + 1).x;
}
snake.get(lastIndex).x += size;
drawSnake(gc);
}
private void drawSnake(GraphicsContext gc) {
snake.forEach(block -> {
gc.fillRoundRect(block.getX(), block.getY(), size, size, 3, 3);
});
}
private Node scenegraphApproach() {
Pane pane = new Pane();
pane.setStyle("-fx-background-color:red;");
pane.setPrefSize(width, height);
for (int i = 0; i < 3; i++) {
Rectangle block = new Rectangle(size, size, Color.GREEN);
// Position the shapes in the Pane using the layoutX/Y properties.
block.setLayoutX(startX + (i * size));
block.setLayoutY(startY);
pane.getChildren().add(block);
shapes.add(block);
}
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(speed), e -> run()));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
return pane;
}
private void run() {
int lastIndex = shapes.size() - 1;
for (int i = 0; i < lastIndex; i++) {
shapes.get(i).setLayoutX(shapes.get(i + 1).getLayoutX());
}
shapes.get(lastIndex).setLayoutX(shapes.get(lastIndex).getLayoutX() + size);
}
}

How to make pyramid patterns of Circle shape using GridPane in javafx

i wanna create pyramid left,right,center angle, using Circle shape in GridPane, i have already done with the left angle, but spent 2 days in creating right and center angle with no luck.
i will be thankful if anyone knows or can give me some algo ideas please help me!
Output already done left angle
With the following code
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
Circle circle = new Circle();
circle.setStroke(Paint.valueOf(Color.BLACK.toString()));
circle.radiusProperty().bind(ballsModel.radiusProperty());
circle.strokeWidthProperty().bind(ballsModel.strokeProperty());
circle.fillProperty().bind(Bindings.createObjectBinding(() -> Paint.valueOf(ballsModel.getColor().name())));
grid.addRow(i, circle);
}
}
Need to figure out following patterns:
center angle
right angle
an example for the pyramid part
package pyramid;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Pyramid extends Application {
void createPyramid(){
gridPane.setHgap(5);
gridPane.setVgap(5);
int center = 4 ;
for (int row = 0; row <= 4; row++ ) {
int range = (1 +(2* row));
int startColumn = center-range/2 ;
for(int i = 0 ; i<range; i++){
Circle circle = new Circle(20,javafx.scene.paint.Color.BLUE);
gridPane.add(circle,startColumn+i , row);
}
}}
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.getChildren().add(gridPane);
this.createPyramid();
Scene scene = new Scene(root, 600, 600);
primaryStage.setTitle("Pyramid");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}}

JavaFX GridPane contains non defined spacing

Iam trying to add some Labels to a GridPane.
Those Labels contain ImageViews which contain some Images.
My images are .png-images and are 50 x 50 pixels big.
If my GridPane is getting to big to display it on my screen, I want to resize my Images. Iam trying this with the methods setFitWidth and setFitHeight.
Snipped:
#Override
public void start(Stage stage) {
GridPane gridPane = new GridPane();
int ySize = 5;
int xSize = 5;
int imageSize = 25;
for(int i=0 ; i<ySize ; i++) {
for(int j=0 ; j<xSize ; j++) {
ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream("path.png")));
imageView.setFitWidth(imageSize);
imageView.setFitHeight(imageSize);
Label label = new Label();
label.setGraphic(imageView);
gridPane.add(label, i, j);
}
}
stage.setScene(new Scene(gridPane));
stage.show();
}
The output looks fine:
However, if imageSize is getting to small, for example 10, a horicontal spacing appears between the rows:
Is there any way to remove this? I tried to set the label sizes max-properties:
label.setMaxHeight(imageSize);
label.setMaxWidth(imageSize);
with no effect.
Is there any way to remove the spacing? Is it because the images are .png's?
Thank you

GridPane.getColumnIndex() returning null

Trying to add children to a GridPane with row and column indices. They show up in the gui, but using GridPane.getColumnIndex(node) always returns null.
GridPane grid = new GridPane();
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
grid.setGridLinesVisible(true);
Button myBtn = new Button("foo");
GridPane.setColumnIndex(myButton,i);
GridPane.setRowIndex(myButton,j);
grid.getChildren().add(myButton);
}
When I try to use this algorithm I got from the answer on javafx GridPane retrive specific Cell content, the program crashes with a NullPointerException.
private Node getNodeFromGridPane(GridPane gridPane, int col, int row)
{
for (Node node : gridPane.getChildren()) {
if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
return node;
}
}
return null;
}
Why are GridPane.getRowIndex() and GridPane.getColumnIndex() returning null even after calling setColumnIndex() and setRowIndex()?
So it seems I got it to work if you run it you will see that all the buttons are red white or blue this is because they were found
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
GridPane grid = new GridPane();
grid.setGridLinesVisible(true);
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
grid.add(new Button("foo"),i,j);
// Button myBtn = new Button("foo");
// GridPane.setColumnIndex(myBtn, i);
// GridPane.setRowIndex(myBtn, j);
// grid.getChildren().add(myBtn);
}
}
Scene scene = new Scene(grid);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
String[] colors = {"-fx-background-color: red;", "-fx-background-color: blue;", "-fx-background-color: white;"};
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
Node node = getNodeFromGridPane(grid,i,j);
if(node instanceof Button)
node.setStyle(colors[(int) (Math.random() * 3)]);
}
}
}
private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
for (Node node : gridPane.getChildren())
if (GridPane.getColumnIndex(node) != null
&& GridPane.getColumnIndex(node) != null
&& GridPane.getRowIndex(node) == row
&& GridPane.getColumnIndex(node) == col)
return node;
return null;
}
public static void main(String[] args) { launch(args); }
}

JavaFX rotate rectangle about center?

I'm trying rotate a rectangle around its center. The rotation is being drawn to a canvas using the GraphicsContext ie gc. Here is my draw code.
gc.save();
gc.translate(center.x, center.y);
gc.rotate(this.angle);
gc.strokeRect(0,0, this.width, this.height);
gc.restore();
This moves the rectangle to its center but then it rotates the rectangle around its top left point. I tried subtracting half the length and width of the sides but that just made it fly all over the place. I suck at math maybe someone here who is better can show me what I'm doing wrong.
I also have stored all four points (corners) of the rectangle if that information is needed.
Thanks,
Joe
A rotation around a specified point needs to be composed from translate transformations and rotations around the origin as follows:
Use translation to move the center of the rotation to the origin.
rotate around the origin
use inverse translation to the first translation
The third part is missing from your code.
Example
#Override
public void start(Stage primaryStage) throws Exception {
Canvas canvas = new Canvas(400, 400);
double x = 50;
double y = 100;
double width = 100;
double height = 200;
GraphicsContext gc = canvas.getGraphicsContext2D();
double rotationCenterX = (x + width) / 2;
double rotationCenterY = (y + height) / 2;
gc.save();
gc.translate(rotationCenterX, rotationCenterY);
gc.rotate(45);
gc.translate(-rotationCenterX, -rotationCenterY);
gc.fillRect(0, 0, width, height);
gc.restore();
Scene scene = new Scene(new Group(canvas));
primaryStage.setScene(scene);
primaryStage.show();
}
You could also simply use a Rotate with a specified pivot to achieve the desired effect:
#Override
public void start(Stage primaryStage) throws Exception {
Canvas canvas = new Canvas(400, 400);
double x = 50;
double y = 100;
double width = 100;
double height = 200;
GraphicsContext gc = canvas.getGraphicsContext2D();
double rotationCenterX = (x + width) / 2;
double rotationCenterY = (y + height) / 2;
gc.save();
gc.transform(new Affine(new Rotate(45, rotationCenterX, rotationCenterY)));
gc.fillRect(0, 0, width, height);
gc.restore();
Scene scene = new Scene(new Group(canvas));
primaryStage.setScene(scene);
primaryStage.show();
}
It's just so simple, like below.
Rectangle rect = new Reactangle(20, 20, 100, 50);
rect.setRotate(30); //rotate the rectangle around its center by 30 degrees.

Resources