0

I'm getting a java.lang.NullPointerException on my super.paintComponent(e) line, I have looked at a few tutorials but I'm unsure of what I'm doing wrong.

Heres my Main class:

package pack;

public class Main  {    
public static void main(String[] args){     
    @SuppressWarnings("unused")
    Display display = new Display("The JFrame", 510, 510);          
    Game game = new Game();
    game.start();
}
}

Display class:

    package pack;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Display {
private JFrame frame;
private String title;
private int width, height;
private static JPanel canvas;

public Display(String title, int width, int height) {
    this.title = title;
    this.width = width;
    this.height = height;       
    createDisplay(); 
}

private void createDisplay(){       
    frame = new JFrame(title);   
    frame.setSize(width, height); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true);             
    canvas = new JPanel();                  
    canvas.setPreferredSize(new Dimension(width, height)); 
    canvas.setMaximumSize(new Dimension(width, height));   
    canvas.setMinimumSize(new Dimension(width, height));    
    frame.add(canvas);          
    frame.pack();           
    }

public static JPanel getCanvas(){       
    return canvas;              
}
}

And finaly the Game class where the error occurs:

    package pack;

import java.awt.Graphics;
import javax.swing.JPanel;

public class Game extends JPanel implements Runnable {

private Thread thread;
private boolean running = false;
public Graphics e;

public synchronized void stop() {       
if(running = false){
    return;         
}       
running = false;    
try {
        thread.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       
}  

public synchronized void start() {      
    if(running)
        return;     
    running = true;
    thread = new Thread(this);  
    thread.start();     
}   

@Override
public void run() {     
int fps = 60;
double timePerTick = 1000000000 / fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
@SuppressWarnings("unused")
int ticks = 0;
long timer = 0; 
while(running)  {       
    now = System.nanoTime();        
    delta += (now - lastTime) / timePerTick;        
    timer += now - lastTime;        
    lastTime = now;     
    if(delta >= 1){ 

        paintComponent(e);  //ERROR LINE

ticks++;    
delta--;    
    }   
    if(timer >= 1000000000){
        ticks = 0;
        timer = 0;
    }   
 }
stop();
}   

@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);                    
}       
}

If I replace

super.paintComponent(e) 

with

g = Display.getCanvas().getGraphics(); 

The error no longer occurs.

Aquan1111
  • 65
  • 1
  • 7
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). – Andrew Thompson Mar 07 '15 at 14:54
  • 1
    I'm going to look at your code, but please for your own benefit and ours, learn to format your code well. Bad formatting makes code hard to read and thus hard to interpret, leading to no answers or wrong answers. Also avoid over-use and likely mis-use of static. Also, you should not have a Graphics field, g. That spells disaster. – Hovercraft Full Of Eels Mar 07 '15 at 14:55
  • 1
    `private Graphics g;` That doesn't bode well. A `Graphics` object should be considered transient, and never be cached.. – Andrew Thompson Mar 07 '15 at 14:56
  • Edit: I've tried to format your code for you. – Hovercraft Full Of Eels Mar 07 '15 at 14:56
  • 1
    Maybe I am blind ... but where do you initialize your "Graphics g"? I just saw the declaration; so for sure, g will be null later on ... – GhostCat Mar 07 '15 at 14:59
  • `g = Display.getCanvas().getGraphics();` -- this is a very dangerous thing to do as it will give you a Graphics object that will not persist leading to unstable graphics. Instead and as several of us have told you, **get rid of your Graphics field**, g. It has no place in this program. – Hovercraft Full Of Eels Mar 07 '15 at 16:16

1 Answers1

2

Change:

paintComponent(g);

To:

repaint(); //will cause a call to paintComponent with a VALID graphics instance

Working implementation. Besides fixing the error, this code adds an instance of the Game to the frame so it is visible, and does something useful in the paintComponent(..) override so that it can be seen to do anything.

import java.awt.*;
import javax.swing.*;

public class Display {

    private JFrame frame;
    private String title;
    private int width, height;
    private static Game canvas;

    public Display(String title, int width, int height) {
        this.title = title;
        this.width = width;
        this.height = height;
        createDisplay();
    }

    private void createDisplay() {
        frame = new JFrame(title);
        frame.setSize(width, height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        canvas = new Game();
        canvas.start();
        canvas.setPreferredSize(new Dimension(width, height));
        canvas.setMaximumSize(new Dimension(width, height));
        canvas.setMinimumSize(new Dimension(width, height));
        frame.add(canvas);
        frame.pack();
    }

    public static JPanel getCanvas() {
        return canvas;
    }

    public static void main(String[] args) {
        Display display = new Display("The JFrame", 510, 510);
    }
}

class Game extends JPanel implements Runnable {

    private Thread thread;
    private boolean running = false;

    public synchronized void stop() {
        if (running = false) {
            return;
        }
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void start() {
        if (running) {
            return;
        }
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        int fps = 60;
        double timePerTick = 1000000000 / fps;
        double delta = 0;
        long now;
        long lastTime = System.nanoTime();
        @SuppressWarnings("unused")
        int ticks = 0;
        long timer = 0;
        while (running) {
            now = System.nanoTime();
            delta += (now - lastTime) / timePerTick;
            timer += now - lastTime;
            lastTime = now;
            if (delta >= 1) {

                //paintComponent(e);  //ERROR LINE
                repaint();

                ticks++;
                delta--;
            }
            if (timer >= 1000000000) {
                ticks = 0;
                timer = 0;
            }
        }
        stop();
    }

    int x=0;
    int y=0;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawLine(0, 0, x++, y++);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    Good catch! How did you find that in all the unrelated dross? – Hovercraft Full Of Eels Mar 07 '15 at 14:59
  • @HovercraftFullOfEels Your formatting of the code helped.. :) – Andrew Thompson Mar 07 '15 at 15:00
  • @AndrewThompson Thank you for the help, and sorry for the bad formatting, i just recently started coding in general, i will try to make it better before posting anything else here. I have tried using repaint() instead of paintComponent(g); however it just leaves the panel blank. – Aquan1111 Mar 07 '15 at 15:05
  • @Aquan1111: your code appears overly complex and it appears that you're asking the Game class to do too much, to have too much responsibility. Try breaking down that class into smaller *testable* units of code, and then if you run into problems you can test each small part in isolation. Strive for an M-V-C like pattern if you can where your code logic is separate from your GUI. – Hovercraft Full Of Eels Mar 07 '15 at 15:06
  • 1
    *"i will try to make it better before posting anything else here."* Make it an MCVE if you want more help. One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Mar 07 '15 at 15:14
  • @AndrewThompson I edited the post, i believe this time i left only the essential to reproduce the problem. – Aquan1111 Mar 07 '15 at 15:54
  • 1
    `paintComponent(e); //ERROR LINE` I *already* indicated what to do in order to fix that.. – Andrew Thompson Mar 07 '15 at 15:59
  • I was bored, so I decided to spoon-feed the solution. See the edit. – Andrew Thompson Mar 08 '15 at 04:25