0

I am working on a paint app project and am working on an "undo" function. I have created an undrawHandler ActionEvent method to handle this and when I run my code my whole canvas is cleared instead of removing the last shape in the array list and I am getting an error: Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "Circle.draw(javafx.scene.canvas.GraphicsContext)" because "this.shape" is null

Here is my code:

import javafx.application.Application;
import javafx.css.Size;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.control.TextField;
import javafx.scene.text.*;
import java.util.ArrayList;


public class PaintApp extends Application {

    // TODO: Instance Variables for View Components and Model
    private ArrayList<GeometricObject> shapes;
    private GraphicsContext gc;
    private TextField rField;
    private TextField gField;
    private TextField bField;
    private TextField brushSize;
    boolean drawCircle = true;
    private ActionEvent e;
    private Circle shape;


    // TODO: Private Event Handlers and Helper Methods

    private void mouseEventHandler(MouseEvent me) {

        int red = 0;
        int blue = 0;
        int green = 0;
        int size = 10;
        String col;
        // location for drawing
        double x = me.getX();
        double y = me.getY();
        // color for drawing

        try {
            red = Integer.parseInt(rField.getText());
            blue = Integer.parseInt(bField.getText());
            green = Integer.parseInt(gField.getText());
            size = Integer.parseInt(brushSize.getText());

            // Check all these values are between 0 and 255 - if not update error label
        }catch(NumberFormatException e)
        {
            // Update error label on screen to notify user of problem
            return; // exit the method, don't keep going
        }

        // going to draw
        GeometricObject shape;

      if (drawCircle)
            shape = new Circle(x,y, Color.rgb(red, green, blue), size);
       else
            shape = new Square(x,y, Color.rgb(red, green, blue), size);

        shape.draw(gc);
        shapes.add(shape); // add the shape to my arraylist to keep track of order drawn

    }

    private void undrawHandler(ActionEvent e)
    {

        int index = shapes.size() - 1; // remove the last item from the arraylist
        shapes.remove(index);

        gc.setFill(Color.WHITE);
        gc.fillRect(0,0,800,400);  // redraw the white rectangle ( the background)

        // redraw the canvas with everything else

        // redraw all shapes in the arrayList (loop)

        if (!shapes.isEmpty())
       {
           shape.draw(gc);
       }

    }

    /**
     * This is where you create your components and the model and add event
     * handlers.
     *
     * @param stage The main stage
     * @throws Exception
     */
    @Override
    public void start(Stage stage) throws Exception {
        Pane root = new Pane();
        Scene scene = new Scene(root, 800, 500); // set the size here
        stage.setTitle("FX GUI Template"); // set the window title here
        stage.setScene(scene);
        // TODO: Add your GUI-building code here



        // 1. Create the model
        shapes = new ArrayList<>();
        // 2. Create the GUI components
        Canvas c = new Canvas(800,400); // used for Mouse events
        gc = c.getGraphicsContext2D();

        rField = new TextField();
        gField = new TextField();
        bField = new TextField();
        brushSize = new TextField();
        Label col = new Label("Color:");
        Label size = new Label("Size:");
        Button draw = new Button("Draw");
        Button undraw = new Button("UnDraw");
        Button circle = new Button("Circle");

        circle.setOnMousePressed((event) -> {
            drawCircle = true;
        });
        Button square = new Button("Square");
        square.setOnMousePressed((event) -> {
            drawCircle = false;
        });

        undraw.setOnMousePressed((event) -> {
            undrawHandler(e);
                });


        // 3. Add components to the root
        root.getChildren().addAll(rField, gField, bField,col,draw, circle, square,brushSize,size,undraw, c);
        // 4. Configure the components (colors, fonts, size, location)
        circle.relocate(10,430);
        square.relocate(65,430);
        rField.relocate(465,430);
        rField.setPrefWidth(50);
        bField.relocate(515,430);
        bField.setPrefWidth(50);
        gField.relocate(565,430);
        gField.setPrefWidth(50);
        size.relocate(340,430);
        brushSize.relocate(370,430);
        brushSize.setPrefWidth(50);
        col.relocate(430,430);
        draw.relocate(625,430);
        undraw.relocate(675,430);

        // 5. Add Event Handlers and do final setup
        gc.setFill(Color.WHITE);
        gc.fillRect(0,0,800,400);
        c.addEventHandler(MouseEvent.MOUSE_PRESSED, this::mouseEventHandler);
        c.addEventHandler(MouseEvent.MOUSE_DRAGGED, this::mouseEventHandler);
        // 6. Show the stage
        stage.show();
    }

    /**
     * Make no changes here.
     *
     * @param args unused
     */
    public static void main(String[] args) {
        launch(args);
    }
}
dlohammer
  • 1
  • 1
  • 1
    Please add the full stack trace of your exception to your question. – tgdavies Aug 13 '21 at 01:10
  • 1
    In the code in your question, you never assign a value to member `shape` of class `PaintApp`. Hence it is null. It is not clear to me, from the code in your question, what value should be assigned to `paint` and in which method to assign a value. Also, in method `mouseEventHandler`, you have a local variable also named `shape`. Perhaps you are confusing the local variable with the class member? Maybe try giving the local variable a different name? I suggest `genericShape`. – Abra Aug 13 '21 at 05:15

0 Answers0