简体   繁体   中英

Java Swing NullPointerException when drawing

I'm using a custom JLayeredPane. I have several Shapes which needed to be drawn on different layers in the JLayeredPane.

To test this I create a JPanel and ask its graphics. Then I draw a test rectangle on that JPanel (preparing the graphics) and in my paintComponent method from the JLayeredPane I finally draw everything. But this fails (NullPointerException).

public class MyCustomPanel extends JLayeredPane {

// test
JPanel testpane;
Graphics g2;
// test

// constructor
public MyCustomPanel() {
    testpane = new JPanel();
    this.add(testpane, new Integer(14));
    g2 = testpane.getGraphics();
}

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

    g2.drawRect(10, 10, 300, 300);
}

}

// run:
//Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
//        at view.MyCustomPanel.paintComponent(MyCustomPanel.java:65)

Why can't I draw on such a JPanel from within my JLayeredPane? I can draw directly on my JLayeredPane from within my paintComponent method but that's on the default Panel from the JLayeredPane. I need to create and draw on several layers which are added in my JLayeredPane.

What am I doing wrong? :s

You should use g2 casting the Graphics that is passed to you:

Graphics2D g2 = (Graphics2D)g;

Why don't you try decoupling things?

class InnerPanel extends JPanel
{
  public void paint(Graphics g)
  {
     Graphics2D g2 = (Graphics2D)g;
     g2.drawRect(....);
  }
}

class MyLayered extends JLayeredPane()
{
  MyLayered()
  {
    this.add(new InnerPanel(), 14);
  }
}

this makes more sense..

Also because you are trying to do something that doesn't agree with Swing behaviour. Swing will care by itself to call the appropriate paint methods over things that must be displayed, and to go with this protocol you should tell Graphics objects what to draw when Swing asks it to your objects (calling the paint ) method, not when you want to do it.

In this way whenever Swing wants to draw your JLayeredPane you just draw things on a Graphic object of other things without considering that Swing will call their appropriate methods when it's the right time to do so.

In conclusion: you can't draw something on a Graphic object when you want it. You can do it just inside methods invoked by Swing, because otherwise Graphics of these objects doesn't mean anything

The variable g2 is probably null because you set it in the constructor, not when drawing. Instead, use the "g" that was passed in.

You can only get a legitimate Graphics from a component that is currently being painted. Otherwise, it's not valid. At the point you're requesting it, the MyCustomPanel() isn't being displayed, and neither is testpane.

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