Hello again, got another Java question.

I am trying to draw an oval from the Alien class to the Canvas in the Game class.

Here is the code

import javax.swing.*;
import java.awt.*;
/**
 * The Evil Ovals!
 * 
 * @author Eric Foertsch 
 * @version Nov 2009(1.0.0a)
 */
public class Alien extends Canvas{
    // X pos
    private int x;
    // Y pos
    private int y;
    // Width
    private int w;
    // Height
    private int h;
    // Ship Color
    private Color color;
    // Missle Color
    private Color missleColor;
    // Background Color
    private Color background;
    // Probability of missle firing
    private double missleLaunchProb;
    // Wall location
    private int wall;
    // Missle
    private Missle pewPew;
    // Velocity
    private int velocity;

    /**
     * Constructor for objects of class Alien
     */
    public Alien(int pX, int pY, int pW, int pH, Color pColor, Color pMissleColor, Color pBackGround,
    double pMissleLaunchProb, int pWall){
        x = pX;
        y = pY;
        w = pW;
        h = pH;
        color = pColor;
        missleColor = pMissleColor;
        background = pBackGround;
        missleLaunchProb = pMissleLaunchProb;
        wall = pWall;
        pewPew = new Missle(x, y, w, h, 10, Color.red, 500);
        velocity = 10;
    }

    /**
     * Returns a Missle
     */
    public Missle getMissle(){
        return pewPew;
    }
    
    /**
     * Draws a Alien
     */
    public void draw(Graphics g, Color pColor){
        
     // Draws an Alien
    g.setColor(pColor);
    g.drawOval(x, y, w, h);
    }
    
    /**
     * Moves the alien and missle
     */
    public void move(Graphics g){
        
        // Moves the Alien Ship
        draw(g, background);
        if(x > 600){
            velocity = -10;
        }
        if(x < 0){
            velocity = 10;
        }
        x = x + velocity;
        draw(g, color);
        
        // Missle
        if(pewPew == null){
            if(Math.random() >= missleLaunchProb){
                pewPew.move(g, background);
            }
        }
    }
    
    /**
     * Returns if the missle has hit
     */
    public boolean isHit(Graphics g, Missle enemyMissle){
        if(enemyMissle.getNose() == new Point(x + w, y + h)){
        return true;
        }
    return false;
    }
    
    /**
     * Erases the ship if destroyed.
     */
    public void remove(Graphics g){
        pewPew.draw(g, background);
        draw(g, background);
        pewPew = null;
    }
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
 * Holds the rules for the game.
 * 
 * @author Eric Foertsch
 * @version Nov 2009(1.0.0a)
 */
public class Game implements ActionListener, Runnable, MouseMotionListener, MouseListener
{
        // Frame of the Board
    private JFrame f;
    
    // Sets a Quit item
    private JMenuItem Quit;
    
    // Start Button
    private JButton start;
    
    // Canvas
    private Canvas c;
    
    // Graphics
    private Graphics2D graphic;
    
    // Alien Array
    private Alien[] a;
    
    // Ship X
    private int x;
    
    // Ship Y
    private int y;
    
    // Ship H
    private int h;
    
    // Ship W
    private int w;
    
    // Missle
    private Missle moarPewPew;
    
    // Text Field
    private JTextField txt;
    
    // Graphics
    private Graphics g;
    
    /**
     * Constructor for objects of class GUI
     */
    public Game(){
        
    // Start Button
    start = new JButton("Start");
    start.addActionListener(this);
    
    // Canvas
    c = new Canvas();
    c.setSize(500, 400);
    c.setBackground(Color.black);
    c.setVisible(true);
    
    //Text Box
    txt = new JTextField();
    
    // Frame
    f = new JFrame("Attack of the Ovals!");
    f.setSize(600, 500);
    f.setVisible(true);
    f.setLayout(new BorderLayout());

    f.add(txt, BorderLayout.NORTH);
    f.add(c, BorderLayout.CENTER);
    f.add(start, BorderLayout.SOUTH);
    setupMenus(f);
    f.validate();
    
    x = 500;
    y = 400;
    w = 20;
    h = 20;
    
    }

    /**
     * This is a method that sets up the menus for the game.
     */
    public void setupMenus(JFrame frame){
        
        // Sets up the Menu Bar
        JMenuBar menubar = new JMenuBar();
        frame.setJMenuBar(menubar);
        
        //Sets up the Game Menu
        JMenu gamemenu = new JMenu("Game");
        menubar.add(gamemenu);
        
         //Adds the Quit option to the Game Menu
        JMenuItem quitItem = new JMenuItem("Quit");
        quitItem.addActionListener(this);
        gamemenu.add(quitItem);
    }
    
    /**
     *  This is a method for actions.
     */
     public void actionPerformed(ActionEvent e){
         
      // Quit Action
           if(e.getActionCommand() == "Quit"){
                int n = JOptionPane.showConfirmDialog(null,
                "Are you sure you want to quit?", "The Ovals will kill us all!!", 
                JOptionPane.YES_NO_OPTION);
                if(n == JOptionPane.YES_OPTION){
                System.exit(1);
                }
                if(n == JOptionPane.NO_OPTION){
                JOptionPane.showMessageDialog(null, 
                "We still have a chance", "Fight on!", 
                JOptionPane.INFORMATION_MESSAGE);
                }
            }
            
            if(e.getActionCommand() == "Start"){
                playRound(g);
            }
      }

      /**
       * This method will play a round of the Game.
       */
      public void playRound(Graphics g){
          c.getGraphics();
          c.setVisible(true);
          boolean gameOver = false;
          
          
          // Sets up the Array of Aliens
            a = new Alien[3];
            Alien Bob = new Alien(40, 40, 10, 10, Color.yellow, Color.red, Color.black, .3, 500);
            Alien Betty = new Alien(100, 100, 10, 10, Color.yellow, Color.red, Color.black, .5, 500);
            Alien Daisuke = new Alien(150, 150, 10,  20, Color.yellow, Color.red, Color.black, .8, 500);
                a[0] = Bob;
                a[1] = Betty;
                a[2] = Daisuke;
                
             // Starts up the game
             if(gameOver == false){
              
              // Draws the Aliens
              Bob.draw(g, Color.yellow);
              Betty.draw(g, Color.yellow);
              Daisuke.draw(g, Color.yellow);
              
              // Moves the Aliens
            Bob.move(g);
            Betty.move(g);
            Daisuke.move(g);
            }
          
          // Removes an alien if destroyed
          for(int i = 0; i < a.length; i++){
             if(a[i].isHit(g, moarPewPew) == true){
                 a[i].remove(g);
            }
            }
        }
        
        /**
         *  Checks to see if my ship is hit.
         */
        private boolean isHit(Missle enemyMissle){
            if(enemyMissle.getNose() == new Point(x + w, y + h)){
                return true;
            }
                return false;
        }
        
        /**
         *  Draws my ship
         */
        private void draw(Color pColor){
         c.getGraphics();
         g.setColor(pColor);
         g.fillRect(x, y, w, h);
        }
        
        /**
         *  Mouse Movement Methods
         */
        public void mouseMoved(MouseEvent e){
            if((x > 500 || x < 0) && (y > 400 || y < 0)){
            draw(Color.black);
            x = e.getX();
            y = e.getY();
            draw(Color.blue);
            }
        }
        
        public void mouseClicked(MouseEvent e){
            if(moarPewPew == null){
            moarPewPew = new Missle(x, y, 10, 20, 10, Color.green, 0);
            moarPewPew.move(g, Color.black);
            }
        }
        
        public void run(){
            playRound(g);
        }
        
        /**
         *  Slows down the game so it is playable.
         */
        private void pause(int msecs){
            try{
                    Thread.sleep(msecs);
             }
            catch(InterruptedException e){}
        }
        
        /**
         *  Resets the game
         */
        private void reset(){
            moarPewPew.draw(g, Color.black);
            moarPewPew = null;
            a[0].draw(g, Color.black);
            a[1].draw(g, Color.black);
            a[2].draw(g, Color.black);
            a[0].remove(g);
            a[1].remove(g);
            a[2].remove(g);
            
        }
        
        /**
         *  Methods to make program run.
         */
       public void mouseDragged(MouseEvent e){
        }
        
       public void mousePressed(MouseEvent e){
        }
        
       public void mouseReleased(MouseEvent e){
        }
        
       public void mouseEntered(MouseEvent e){
        }
        
       public void mouseExited(MouseEvent e){
        }

}

When I hit the start button, it throws this error at me

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Alien.draw(Alien.java:64)
at Game.playRound(Game.java:154)
at Game.actionPerformed(Game.java:128)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6263)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Via this error, I know its something wrong with the draw() method in the alien class, but I am at a loss as to what is wrong.

Any help appreciated.

Rolfninja

Dani AI

Generated

Quick diagnosis (from the stack trace): the NullPointerException is thrown inside Alien.draw because the Graphics reference used there is null. In the Game code the field g is never initialized and calls like c.getGraphics() are made without assigning or using the returned Graphics — so when playRound(g) calls Alien.draw(g, ...) the g argument is null. Also worth noting: mixing AWT Canvas and Swing components and keeping a Graphics reference as a field are both fragile patterns.

What to do instead (follow Swing painting model — pointed this out):

  • Make a lightweight drawing surface (extend JPanel), override paintComponent(Graphics g), call super.paintComponent(g), and do all drawing there.
  • Keep Aliens as plain model objects with move() and paint(Graphics2D g) methods (do not have them extend Canvas).
  • Drive animation with a javax.swing.Timer: update model (positions, missiles) in the timer action and call repaint(); let paintComponent render the current model.

Minimal example pattern (illustrative — not a drop-in of original code):

class GamePanel extends JPanel {
    private java.util.List<Alien> aliens = new ArrayList<>();
    private Timer ticker = new Timer(40, e -> { aliens.forEach(Alien::move); repaint(); });

    public GamePanel() {
        setPreferredSize(new Dimension(500,400));
        setBackground(Color.BLACK);
        // populate aliens...
        ticker.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        for (Alien a : aliens) a.paint(g2);
    }
}

And a simple Alien contract:

class Alien {
    int x,y,w,h,vx;
    Color color;
    void move() { x += vx; if (x < 0 || x + w > 600) vx = -vx; }
    void paint(Graphics2D g) { g.setColor(color); g.fillOval(x,y,w,h); }
}

Other practical tips and quick checks:

  • Never store a Graphics object in a field. Do not rely on component.getGraphics() for persistent drawing (it’s temporary and will be lost on the next repaint).
  • Create the GUI on the EDT (SwingUtilities.invokeLater) and use javax.swing.Timer instead of Thread.sleep.
  • Register mouse listeners on the panel (e.g., panel.addMouseMotionListener(...)).
  • Fix string comparisons in listeners: use "Quit".equals(e.getActionCommand()) rather than ==.
  • For a quick one-off test the immediate patch is to call Graphics g2 = c.getGraphics() and pass that to playRound, but that is only a temporary debug step — move to paintComponent for a real fix.

Following this pattern will eliminate the NPE, stop flicker, and make animation and repainting reliable.

Recommended Answers

All 8 Replies

Bump

hi,

in my applet i have a paint components method. not sure if there are any other paint choices,

public void paintComponent(Graphics g)
	{
 	Color mycolor, mycolor2, mycolor3;
	mycolor = new Color(5,0,0);
	setBackground(mycolor);
	super.paintComponent(g);
	// now i can draw shapes with the g2 methods 
                Graphics2D g2 = (Graphics2D) g;

when i want to update the drawing i call repaint() or repaint(x,y, width, hight);


notice paintComponents expects to pass in Graphics g;

one thing i couldnt figure out from your draw was where your g in draw was getting its knowledge from or even defined. paintcomponents passes in the graphics object.

Mike

this is the code i coudlnt see where g was defined

private void draw(Color pColor){ c.getGraphics(); g.setColor(pColor); g.fillRect(x, y, w, h); }


Mike

Which method would I define the G in?

I couldn't instantiate a g object, and I am unsure as to how to pass it the correct g object.

Oh and I have no experience with paintComp, If possible I'd like to stay within graphics class...

Oh and I have no experience with paintComp, If possible I'd like to stay within graphics class...

i'm not sure how i found paint components, its a standard method not defined by me.

the beauty of it is when java calls it, which is whenever anything needs to be drawn, it passes in g.

All your methods that use g could be called from paint components. just assume paint components is called whenever anything needs to be drawn or painted and you can invoke an update of the drawing with repaint() or you can define the area to repaint if you just channge an area with repaint( x, y, width , hight);

Mike

oh i just added paintComponents to my panel , just insert below and i believe it will work. its called by teh system when something needs to be drawn. you draw the whole screen. if repaint(x , y , width, height) is used you don't know that in paint but that is the area of the screen refreshed. if your class is in the scope to be used by the panel, it can invoke your draw methods passing g i would assume.

public void paintComponent(Graphics g)
{
super.paintComponent(g);
// now i can draw shapes with the g2 methods 
Graphics2D g2 = (Graphics2D) g;

// do any drawing here 

} // end

mike

I got out my java book and here is what it says:

"In particular, to draw on a panel, you
Define a class that extends Jpanel
Override the paintCommponent method in that class
The paintComponent method is actually in JComponent, the superclass for all non window Swing Components. "

below it says 'here is how to make a panel onto which you can draw:

class MyPanel extends JPanel
{

public void paintComponent(Graphics g)
{
// code for drawing will go here

}

}

Mike

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.