0

I am trying to write a JavaFX program that takes in dimensions from the user using TextField boxes and create two rectangles, draw them, and send a message if they intersect. I am having trouble getting my rectangles to be drawn and I don't know why that is happening. I am also not sure how I can tell if they intersect or not when looking at the values. Any help you can provide would be greatly appreciated, I have posted my code below.

My Code:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.scene.layout.StackPane;
import javafx.geometry.Insets;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.control.*;
import javafx.scene.shape.Rectangle;
public class Rectangles extends Application
{
    Canvas canvas;
    Label intersectLabel;
    TextField x1Text;
    TextField x2Text;
    TextField y1Text;
    TextField y2Text;
    TextField width1Text;
    TextField width2Text;
    TextField height1Text;
    TextField height2Text;

    @Override
    public void start(Stage stage) throws Exception
    {
        // Create a VBox to stack panes vertically
        VBox panesStack = new VBox(20);
        // Create padding of 10 pixels
        Insets padding = new Insets(10);

        // Create labels and text fields for rectangle 1 info
        Label x1Label = new Label("X:");
        // Create labels and field for r1.
        TextField x1Text = new TextField();
        Label y1Label = new Label("Y:");
        TextField y1Text = new TextField();
        Label width1Label = new Label("Width:");
        TextField width1Text = new TextField();
        Label height1Label = new Label("Height:");
        TextField height1Text = new TextField();

        // Create grid pane for rectangle 1 info, set spacing
        GridPane grid1 = new GridPane();
        grid1.setPadding(padding);
        grid1.setHgap(10);
        grid1.setVgap(5);

        // Add rectangle 1 labels and text fields to grid pane
        // First add the top label to span two columns
        grid1.add(new Label("Enter Rectangle 1 info:"),0,0,2,1);
        grid1.add(x1Label,0,1);
        // Add rest of labels and text fields to grid pane
        grid1.add(x1Text,1,1);
        grid1.add(y1Label,0,2);
        grid1.add(y1Text,1,2);
        grid1.add(width1Label,0,3);
        grid1.add(width1Text,1,3);
        grid1.add(height1Label,0,4);
        grid1.add(height1Text,1,4);

        // Create labels and text fields for rectangle 2 info
        Label x2Label = new Label("X:");
        TextField x2Text = new TextField();
        Label y2Label = new Label("Y:");
        TextField y2Text = new TextField();
        Label width2Label = new Label("Width:");
        TextField width2Text = new TextField();
        Label height2Label = new Label("Height:");
        TextField height2Text = new TextField();

        // Create grid pane for rectangle 2 info, set spacing
        GridPane grid2 = new GridPane();
        grid2.setPadding(padding);
        grid2.setHgap(10);
        grid2.setVgap(5);

        // Add rectangle 2 labels and text fields to grid pane
        // First add the top label to span two columns
        grid2.add(new Label("Enter Rectangle 2 info:"),0,0,2,1);
        // Add field and labels
        grid2.add(x2Label,0,1);
        grid2.add(x2Text,1,1);
        grid2.add(y2Label,0,2);
        grid2.add(y2Text,1,2);
        grid2.add(width2Label,0,3);
        grid2.add(width2Text,1,3);
        grid2.add(height2Label,0,4);
        grid2.add(height2Text,1,4);

        // Add the two rectangle info grid panes to an HBox
        // (so they appear horizontally)
        // then add the HBox to the overarching vertical box (panesStack)
        HBox rectGrids = new HBox(30);
        rectGrids.getChildren().add(grid1);
        rectGrids.getChildren().add(grid2);
        panesStack.getChildren().add(rectGrids);

        // Create update button
        // Add event handler to button
        // Add it to overarching vertical box (panesStack)
        Button update = new Button("Update");
        update.setOnAction(this::updateGUI);
        panesStack.getChildren().add(new StackPane(update));

        // Create a canvas for drawing the rectangles
        canvas = new Canvas(600, 500);      
        // Get the canvas' graphics context to draw
        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        // Initially make the canvas blank white
        graphicsContext.setFill(Color.WHITE);
        graphicsContext.fillRect(0,0, canvas.getWidth(), canvas.getHeight());

        // Add the canvas to the overarching vertical box (panesStack)
        panesStack.getChildren().add(canvas);

        // Create a label for the intersection message
        intersectLabel = new Label("waiting for rectangle info");
        intersectLabel.setPadding(new Insets(0,0,20,0));
        panesStack.getChildren().add(new StackPane(intersectLabel));

        // Create a scene containing the overarching vertical box
        Scene scene = new Scene(panesStack);             
        stage.setTitle("Rectangles Lab"); // Set window's title
        stage.setScene(scene);            // Set window's scene
        stage.show();
    }
    public void updateGUI(ActionEvent e) {
        Rectangle r1 = new Rectangle();
        r1.setHeight(Double.valueOf(height1Text.getText()));
        r1.setWidth(Double.valueOf(width1Text.getText()));
        r1.setX(Double.valueOf(x1Text.getText()));
        r1.setY(Double.valueOf(y1Text.getText()));

        Rectangle r2 = new Rectangle();
        r2.setHeight(Double.valueOf(height2Text.getText()));
        r2.setWidth(Double.valueOf(width2Text.getText()));
        r2.setX(Double.valueOf(x2Text.getText()));
        r2.setY(Double.valueOf(y2Text.getText()));

        GraphicsContext graphics = canvas.getGraphicsContext2D();
        graphics.fillRect(r1.getX(), r1.getY(), r1.getWidth(), r1.getHeight());
        graphics.setStroke(Color.BLUE);

        graphics.fillRect(r2.getX(), r2.getY(), r2.getWidth(), r2.getHeight());
        graphics.setStroke(Color.RED);

    }
}
user1803551
  • 12,965
  • 5
  • 47
  • 74

2 Answers2

2

First of all, fix your NPE that is a result of shadowing.

Now look inside updateGUI. You are calling graphics.fillRect, but setting graphics.setStroke. The stroke and the fill are different attributes, if you want to fill, call setFill with the desired Paint, and if you want to stroke, call setStroke. Also, you need to set the stroke/fill before you make the draw operation, not after.

As for checking the intersection, look at Shape#intersect or at Node.intersects. The first returns the shape that is a result of the intersection and works for all shapes. The second returns a boolean depending on the rectangular bounds of the node, so it is accurate for rectangles only.

Also, remember to clear the canvas if you need to before each draw.

user1803551
  • 12,965
  • 5
  • 47
  • 74
2

You didn't mention you get a NullPointerException when you run this code, please always include such information, and include the stack trace.

The reason you get the NPE is because the Rectangles class fields height1Text etc are never set. Instead you declare local variables in your code with the same name, instead of assigning the class fields.

When you fix that, the NPE disappears.

Secondly, the rectangles need a fill color, as you are using fillRect, so make sure to set that up. The stroke color will not help you, unless you use drawRect. Also, first set up the color you want (with setFill), then call fillRect, not the other way around.

john16384
  • 7,800
  • 2
  • 30
  • 44