0

so I have class Board that extends JApplet and in it's constructor I make a JPanel that I'll later draw boxes on, but when I try to do getGraphics it returns null :/

JPanel panel;
public Board(int x, int y, int wolfNumber, int hareNumber){
    this.x=x;
    this.y=y;

    wolvesCoords = new int[wolfNumber][2];
    haresCoords = new int[hareNumber][2];

    panel = new JPanel();
    panel.setVisible(true);

    add(panel);
}


public synchronized void write(int xx, int yy, Color c){
    int width=panel.getWidth()/x;
    int height=panel.getHeight()/y;

    Graphics g = panel.getGraphics();
    System.out.println(g);

    g.setColor(c);

    g.drawRect(xx*width, yy*height, width, height);
    g.fillRect(xx*width, yy*height, width, height);


}

public void paint(Graphics g)
{
        super.paint(g);
}

It gives nullpointerexception at line g.setColor(c) as g is null.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
user3369008
  • 105
  • 11
  • 1
    What is this `write` method? Why aren't you calling the drawing code in the `paint` method with that `Graphics` object? – durron597 May 12 '14 at 21:04
  • write method paints on the board. I don't call paint because g is null and that is my current problem. – user3369008 May 12 '14 at 21:05
  • 1
    No, don't call `paint` yourself, Java will call `paint` for you automatically. http://www.oracle.com/technetwork/java/painting-140037.html – durron597 May 12 '14 at 21:07
  • Why would I call drawing code in the paint method? I need to draw only when the method write is called, not when the app starts. – user3369008 May 12 '14 at 21:08
  • possible duplicate of [JApplet - super.paint(); causes flicker](http://stackoverflow.com/questions/7004866/japplet-super-paint-causes-flicker) – durron597 May 12 '14 at 22:07

2 Answers2

3

Yours is a common problem and question and is yet another reason why you shouldn't use a Graphics object obtained by calling getGraphics() on a component. Another reason you shouldn't do this is that if you are successful at getting a non-null Graphics object (which is only available after the component has been rendered), it will not persist, and your image can turn null if any repaints occur.

Instead do what the tutorials advise you to do: Draw with the Graphics object provided to you in the JPanel's paintComponent method. If you want to draw a fixed background, then do so in a BufferedImage, and then draw that BufferedImage in the paintComponent method.


Edit
You ask:

Why would I call drawing code in the paint method? I need to draw only when the method write is called, not when the app starts.

Because that is how Swing graphics is done, because doing it your way is rife with problems (which you're already experiencing). Again, don't guess at this stuff -- read the tutorials where it is all well explained for you.


Edit
You state in comment:

Actually this error shows up when I try to add override - method does not override or implement a method from a supertype. Could it be that I am extending JApplet?

Yes, exactly so.

I have to though

Yes, you have to have a class that extends JApplet in order to produce JApplets, but you don't have to and in fact shouldn't paint directly in them. Instead create a separate class that extends JPanel, and do your graphics inside of that class's paintComponent method. Then display that JPanel in your applet.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I want to use getGraphics however, can you explain "after the component has been rendered" ? Is my panel not rendered in this example? What should I do to render it? – user3369008 May 12 '14 at 21:10
  • 1
    @user3369008: Again, **don't** use `getGraphics()`. That is not how you should be doing Swing Graphics. Period. – Hovercraft Full Of Eels May 12 '14 at 21:11
  • @user3369008: please check out [these links](http://stackoverflow.com/tags/swing/info). Please also search this site for similar questions and answers, since this has all been hashed and rehashed here many times. – Hovercraft Full Of Eels May 12 '14 at 21:12
  • @user3369008: please see edit to answer regarding your latest comment about overriding applets. – Hovercraft Full Of Eels May 12 '14 at 21:33
  • I voted to close as duplicate of a question, which, surprising no one, @HovercraftFullOfEels has the accepted answer. – durron597 May 12 '14 at 22:08
3

You are using the Graphics object wrong. Instead of calling write from wherever you call it, instead override paintComponent. You could do something like:

private int xx;
private int yy;
private Color c;

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if(c != null) {
        int width=panel.getWidth()/x;
        int height=panel.getHeight()/y;

        g.setColor(c);

        g.drawRect(xx*width, yy*height, width, height);
        g.fillRect(xx*width, yy*height, width, height);
    }
}

public void write(int xx, int yy, Color c) {
    this.xx = xx;
    this.yy = yy;
    this.c = c;
    repaint();
}
durron597
  • 31,968
  • 17
  • 99
  • 158
  • 2
    Please don't forget to add the super's paintComponent call in your override. Otherwise 1+ for your answer. – Hovercraft Full Of Eels May 12 '14 at 21:14
  • I like this solution, however when I call repaint the method painComponent is not called. Why would that be? – user3369008 May 12 '14 at 21:15
  • @user3369008: if you spell it `painComponent` it won't be called. Be careful with your spelling, and make sure that your method has an `@Override` annotation on top of it. His recommendations and mine are the same, except he needs to add a super call in his method override. – Hovercraft Full Of Eels May 12 '14 at 21:16
  • Actually this error shows up when I try to add override - method does not override or implement a method from a supertype. Could it be that I am extending JApplet? I have to though – user3369008 May 12 '14 at 21:19
  • 1
    getGraphics is not an appropriate means to perform painting in Swing, you won't know when the component needs to be repainted and the contents will be over painted without your knowledge – MadProgrammer May 12 '14 at 21:19
  • 2
    Based on your last comment, don't override paint of top level components, like JApplet, instead, use something like JPanel to one form your custom painting and add it to your top level container – MadProgrammer May 12 '14 at 21:21
  • Hmm ok, it is called now, however there is absolutely no change on screen - it stays gray. When I added JLabels with red background to the panel to test if it displays at all it was red. Any idea? – user3369008 May 12 '14 at 21:44
  • @user3369008 The problem is what MadProgrammer said; don't override paint of top level components. However I don't have enough of your code to be able to fix it, but I think you should be able to at this point. – durron597 May 12 '14 at 22:05