Search code examples
javanullpointerexceptionnull-pointer

Null pointer exception even though nothing on the line is null


I am writing a game, and getting a null pointer exception when I try to draw a basket object, even though I create the basket in the main game constructor, before the timer starts that ends up drawing the basket. The only other object involved in the line with the error is the graphics object of the paint component, but I checked with a print statement and that isn't null either. The weird part is that even though I get the exception at the line where the basket is drawn, the basket image still shows up on the frame, but doesn't update (move) when I hit a key that moves it. Here is the main game class, the basket class, and the full stack trace:

import java.awt.*;
import javax.swing.*;
import java.util.Collections;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.event.*;
import java.util.ArrayList;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class MainGame extends JPanel {
    JFrame frame;
    ArrayList<Ball> balls;
    Basket basket;
    int score;
    int level;
    Timer timer;

    public MainGame() {
        addKeyListener(new TAdapter());
        setFocusable(true);
        frame = new JFrame("Drop catch");
        frame.setSize(800, 800);
        frame.setBackground(Color.BLUE);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        this.setBackground(Color.BLUE);
        frame.getContentPane().add(this);
        //frame.getContentPane().add(textField);
        frame.setVisible(true);
        balls = new ArrayList<Ball>();
        basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);
        timer = new Timer(20, new TimerListener());
        timer.start();
    }

    public static void main(String[] args) {
        MainGame myMainGame = new MainGame();
    }

    public void drawScore(Graphics g) {
        g.drawString(String.valueOf(score), frame.getWidth() / 10, frame.getHeight() / 10);
    }

    public void updateScore() {
        //might want something like this
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(Ball b : balls) {
            b.draw(g);
        }
        boolean test = g == null || basket == null;
        System.out.println(test);//this prints false, so basket and g are both not null
        basket.draw(g);//this is line 57, where the exception is
        drawScore(g);
    }

    public class TimerListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            for(Ball b : balls) {
                b.update();
            }
            basket.update();
            updateScore();
            frame.repaint();
        }
    }

     private class TAdapter extends KeyAdapter {

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("Key released");
            basket.keyReleased(e);
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("Key pressed");
            basket.keyPressed(e);
        }
    }
}
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.io.File;

public class Basket {
    int x;
    int y;
    int vel;
    BufferedImage sprite;

    public Basket(int x_, int y_) {
        x = x_;
        y = y_;
        importImage();
    }

    public void importImage() {
        File imageFile = new File("sprites/basket.jpg");
        try {
            sprite =ImageIO.read(imageFile);
        } catch(Exception e) {e.printStackTrace();}
    }

    public void update() {
        x += vel;
    }

    public void draw(Graphics g) {
        g.drawImage(sprite, x, y, null);
    }

    //movement stuff
    //public class movementListener implements KeyListener {
        public void keyPressed(KeyEvent e) {
            if(e.equals(KeyEvent.VK_KP_LEFT) || e.equals(KeyEvent.VK_A)) {
                vel = -1;
            }
            if(e.equals(KeyEvent.VK_KP_RIGHT) || e.equals(KeyEvent.VK_D)) {
                vel = 1;
            }
            System.out.println("Key pressed in basket");
        }

        public void keyReleased(KeyEvent e) {
            vel = 0;
            System.out.println("Key released in basket");
        }

        public void keyTyped(KeyEvent e) {}
    //}
}
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at MainGame.paintComponent(MainGame.java:57)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
        at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
        at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
        at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5262)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedFPScales(RepaintManager.java:1707)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1616)
        at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
        at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
        at java.desktop/javax.swing.JComponent.paint(JComponent.java:1060)
        at java.desktop/java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
        at java.desktop/sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:75)
        at java.desktop/sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:112)
        at java.desktop/java.awt.Container.paint(Container.java:2002)
        at java.desktop/java.awt.Window.paint(Window.java:3928)
        at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:876)
        at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
        at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
        at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
        at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Solution

  • First of all, your test condition is wrong , it gives you false because Graphics object is not null. If you want to check both objects use &&

    test = grap != null && basket=!null;
    

    Secondly you don't know Swing life cycle, you call frame.getContentPane().add(this); before you init basket and frame.getContentPane().add(this); calls draw before basket was initialized. I don't want to understand what your code does but the simplest solution is to init Basket before you add component into the frame

     public MainGame() {
            addKeyListener(new TAdapter());
            setFocusable(true);
            frame = new JFrame("Drop catch");
            frame.setSize(800, 800);
            frame.setBackground(Color.BLUE);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            this.setBackground(Color.BLUE);
            basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);//init before add 
            frame.getContentPane().add(this);
            //frame.getContentPane().add(textField);
            frame.setVisible(true);
            timer = new Timer(20, new TimerListener());
            timer.start();
        }