简体   繁体   中英

How to get an instance of java.awt.Graphics in a java.applet.Applet?

I am currently coding the game of Snake for my computer science class. However, I ran into a lot of difficulties (since I am the only one in my block that is working alone) and I had to restart.

Right now I am just trying to make an array of objects (named Snake) from the second class (Segment) I made.

I get a NullPointerException on line 26: g.fillRect(xValue, yValue, size, size); Where should I get an instance of Graphics to call this method on?

import java.awt.*;
import java.applet.*;

public class Segment extends Applet
{
   private Graphics g;

   private int xValue;
   private int yValue;
   private int size;

   public Segment () {}

  public Segment(int x, int y)
  {
  xValue = x;
  yValue = y;

  size = 10;

  drawSegment(g);
   }

   public void drawSegment(Graphics g)
   {
      g.fillRect(xValue, yValue, size, size);
   }

  }

import java.awt.*;
import java.applet.*;

public class SnakeGame extends Applet
{
   private Segment[] snake;
   private Graphics g;

   private int length;
   private int sxValue;
   private int syValue;

   public SnakeGame()
   {
      length = 6;
      snake = new Segment[length];
      sxValue = 100;
      syValue = 100;

      for (int c = 0; c < snake.length; c++)
      {
         snake[c] = new Segment(sxValue, syValue);
         sxValue = sxValue + 10;     
      }

      drawSnake(g);

    }

   public void drawSnake(Graphics g)
   {
      for(int counter = 0; counter < length; counter++)
      {
          snake[counter].drawSegment(g);

      }  
    }


}

However, I keep getting errors such as

java.lang.NullPointerException
at Segment.drawSegment(Segment.java:26)
at Segment.<init>(Segment.java:21)
at SnakeGame.<init>(SnakeGame.java:22)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at java.lang.Class.newInstance(Class.java:433)
at sun.applet.AppletPanel.createApplet(AppletPanel.java:799)
at sun.applet.AppletPanel.runLoader(AppletPanel.java:728)
at sun.applet.AppletPanel.run(AppletPanel.java:378)
at java.lang.Thread.run(Thread.java:745)

You declare Graphics g; and do not instantiate it. So you pass a null value to drawSegment(Graphics g) and try to call g.fillRect(xValue, yValue, size, size); on that null object.

The java.awt.Graphics class you're using is just an abstract class. The object needs to be instantiated with some implementation - either by you or the framework.

Since you're using an Applet , which inherits the Component, try Component.getGraphics() to get a graphics object.

private Graphics g = getGraphics();

Then, you call drawing methods in constructors. That's not a good practice. Instantiating an object (an applet, here) and drawing it is not the same.

Also, each class here has its own variable for Graphics. It seems that a single instance should be used for all drawing, passed to each drawable object.

Get a Graphics object from within the paint(Graphics) or paintComponent(Graphics) method of the custom painted component. That time (when requested to do so by the JVM) is the time that an AWT/Swing GUI should be painted. See Performing Custom Painting for more details and working source.

General tips/questions.

  1. Why code an applet? If it is due to the teacher specifying it, please refer them to Why CS teachers should stop teaching Java applets .
  2. Why use AWT? See this answer for many good reasons to abandon AWT using components in favor of Swing.
  3. It is generally considered better to do custom rendering in a Panel , Canvas or JPanel that is added to the top level container, rather than the container itself. This is more easily adaptable in that we might show the panel in an applet, frame, dialog or a layout constraint of another panel. There are also other advantages.
  4. There are two applets above, but only SnakeGame should be an applet. The Segment class should instead just know how to draw itself to a Graphics object when asked to do so. Then SnakeGame can store a list of Segment objects and (when requested) draw each in turn.
  5. Don't declare a constructor for an applet, since there is no way to ensure it is called on the Event Dispatch Thread. Do everything 'the first time only' in the init() method. But seriously, avoid applets as they are an obsolescent technology that will give you nothing but headaches.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM