Hat
Hat

Reputation: 81

How to draw multiple objects on a canvas?

I'm trying to draw multiple objects in a canvas but keep getting a runtime error, below is my GraphicalObject Class:

/*import javafx.scene.canvas.Canvas;*/
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import java.util.Scanner;

public class GraphicalObject { //class
  private Scanner scan;
  private int x;
  private int y;
  private int width;
  private int height;
  //private double xPoints;
  //private double yPoints;
  //private int numPoints;

  /*
   * constructor
   */
  public GraphicalObject(){
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
    //this.xPoints = 0;
    //this.yPoints = 0;
    //this.numPoints = 0;
  }

    public GraphicalObject(int x, int y, int width, int height){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
  }

    //think of get/set methods ie acessor/mutators
    //get x
    //get y
    //get width
    //get height

public void draw(GraphicsContext gc){
  //int numPoints = 5;
  //double[] xPoints = new double[numPoints];
  //double[] yPoints = new double[numPoints];
  //xPoints = [x + (width/2), x + width, x + .8333 width, x + .1667 width, x]
  //yPoints = [y, y + (height/2), y + height, y + height, y + (height/2)]
` gc.setFill(Color.PINK);
  gc.fillRect(this.x, this.y, this.width, this.height);
  //gc.fillPolygon(xPoints, yPoints, numPoints);
}   
}

I can't figure out where I'm going wrong, I think my for loops are okay... I'm able to draw one rectangle but if I say I want to draw two, it lets me input info for one object and then gives a runtime error. This is my canvas class:

/**
 * A basic canvas object that can store and 
 * draw graphical object
 */

import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
import javafx.scene.canvas.GraphicsContext;
import java.util.Scanner;

public class GraphicalObjectCanvas extends Canvas {

  // data fields

  // constants
  public static final int C_WIDTH = 500;
  public static final int C_HEIGHT = 500;

  // instance variables

  /**
   * a scanner object to make the Canvas interactive
   */
  private Scanner scan;

  // TO DO: DECLARE YOUR ARRAY OF GRAPHICAL OBJECTS HERE
  // (AND ANY OTHER INSTANCE VARIABLES YOU NEED TO MAINTAIN YOUR ARRAY)
    GraphicalObject[] graphobs;
    private int index;
    private int numObjects;
  /**
   * Creates a canvas for drawing graphical objects
   * with a size of C_WIDTHxC_HEIGHT pixels
   */
  public GraphicalObjectCanvas() {
    super(C_WIDTH, C_HEIGHT);

    // initialize the scanner object
    this.scan = new Scanner(System.in);

    // find out how many objects the user wants to add
    System.out.println("How many graphical objects do you want?");
     numObjects = scan.nextInt();

    // TO DO: DEFINE YOUR ARRAY OF GRAPHICAL OBJECTS HERE
    graphobs = new GraphicalObject[numObjects]; 


    // for each object they wanted to add...
    for (int i = 0; i < numObjects; i++) {
      this.add();
    }
  }

  public void draw() {

    // clear the picture
    this.clear();

    // get the graphics context from the canvas
    GraphicsContext gc = this.getGraphicsContext2D();

    // TO DO: LOOP THROUGH YOUR ARRAY OF GRAPHICAL OBJECTS
    // AND TELL EACH ONE TO DRAW PASSING THE GRAPHICS CONTEXT (gc) AS INPUT

    for(int i = 0; i < numObjects; i++){
     graphobs[i].draw(gc);
     System.out.println("Object drawn: " + i); //or 1??);
    }
  }

  private void clear() {
    GraphicsContext gc = this.getGraphicsContext2D();
    gc.setFill(Color.WHITE);
    gc.fillRect(0, 0, C_WIDTH, C_HEIGHT);
  }

  private void add() {
    System.out.println("What is the x location of the object?");
    int x = scan.nextInt();
    System.out.println("What is the y location of the object?");
    int y = scan.nextInt();
    System.out.println("What is the width of the object?");
    int width = scan.nextInt();
    System.out.println("What is the height of the object?");
    int height = scan.nextInt();

    // TO DO: USE THE INFORMATION ABOVE TO CREATE A NEW GRAPHICAL OBJECT
    // AND ADD IT TO THE ARRAY OF OBJECTS.
    GraphicalObject gob = new GraphicalObject( x, y, width, height);
    graphobs[index] = gob;
    index++;

    // after adding new object, redraw the canvas
    this.draw();
  }
}

Upvotes: 1

Views: 1709

Answers (1)

d.j.brown
d.j.brown

Reputation: 1842

The problem is that you are invoking GraphicalObject.draw(GraphicsContext) on a null object.

This occurs because you call GraphicalObjectCanvas.draw() at the end of the GraphicalObjectCanvas.add() method and the for loop in GraphicalObjectCanvas.draw() uses numObjects to determine the range of indices. However, you have yet to create and allocate an object to all the indices of the array graphobs when this for loop executes.

To fix this, either do not invoke GraphicalObjectCanvas.draw() at the end of your GraphicalObjectCanvas.add() method, or change the for loop in GraphicalObjectCanvas.draw() to i < index rather than i < numObjects.

For example:

for(int i = 0; i < index; i++){
    graphobs[i].draw(gc);
    System.out.println("Object drawn: " + i); //or 1??);
}

Upvotes: 1

Related Questions