4

I have looked around on the net and found out how to add an image to a JPanel.

This works fine (when image is loaded in ImagePanel constructor), but I'd like to be able to change the image dynamically (ex: on a button key press). I have tried to implement this, but keep on getting an Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException when I click on the button.

Can anyone help ? I am new to Java. Thanks!

Here is my JPanel extended class:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImagePanel extends JPanel{

    private BufferedImage image;

    public ImagePanel() {
        this.loadImage("/home/raph/Images/shortcurt_unity.png");
    }

    public void loadImage(String filename) {
         try {
          this.image = ImageIO.read(new File(filename));
          this.repaint();
       } catch (IOException ex) {
            // handle exception...
       }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
            if (image != null) {
            // Scale it by width
            int scaledWidth = (int)((image.getWidth() * getHeight()/image.getHeight()));
            // If the image is not off the screen horizontally...
            if (scaledWidth < getWidth()) {
                // Center the left and right destination x coordinates.
                int leftOffset = getWidth() / 2 - scaledWidth / 2;
                int rightOffset = getWidth() / 2 + scaledWidth / 2;
                g.drawImage(image, leftOffset, 0, rightOffset, getHeight(), 0, 0, image.getWidth(), image.getHeight(), null);
            }
            // Otherwise, the image width is too much, even scaled
            // So we need to center it the other direction
            else {
                int scaledHeight = (image.getHeight() * getWidth()) / image.getWidth();
                int topOffset = getHeight() / 2 - scaledHeight / 2;
                int bottomOffset = getHeight() / 2 + scaledHeight / 2;
                g.drawImage(image, 0, topOffset, getWidth(), bottomOffset, 0, 0, image.getWidth(), image.getHeight(), null);
            }
        }
    }
}

I init it in my JFrame:

private static ImagePanel jPanel1;

And Netbeans auto-generated the following (extract of jpanel related code):

javax.swing.JPanel jPanel1 = new ImagePanel();

javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 1260, Short.MAX_VALUE)
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 124, Short.MAX_VALUE)
    );

The call I am making from a button:

private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {
    jPanel1.loadImage("/home/raph/Images/shortcurt_unity.png");
}

Note that when in debug, I cannot step into loadImage, I get the exception before reaching it:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at musicchecker.MusicCheckerGUI.jButton10ActionPerformed(MusicCheckerGUI.java:276)
    at musicchecker.MusicCheckerGUI.access$400(MusicCheckerGUI.java:26)
    at musicchecker.MusicCheckerGUI$5.actionPerformed(MusicCheckerGUI.java:124)
    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:6267)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6032)
    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:4577)
    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:2478)
    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)
Community
  • 1
  • 1
phramusca
  • 113
  • 3
  • 13
  • you're right, I haven't noticed. The question indeed is why it is null though it should have bee initiated ? – phramusca May 19 '11 at 19:42
  • 3
    For better help sooner, post an [SSCCE](http://pscode.org/sscce.html). "Netbeans auto-generated the following.." My condolences. – Andrew Thompson May 19 '11 at 20:19

2 Answers2

3

It looks like the static reference to your panel is never getting set:

private static ImagePanel jPanel1;

It's hard to know for sure without seeing all the actual code but it looks like netbeans is creating a reference to a different panel here:

javax.swing.JPanel jPanel1 = new ImagePanel();

try:

jPanel1 = new ImagePanel();
meverett
  • 921
  • 5
  • 6
  • Yes, I have noticed thath, but how can I edit that in Netbeans ? This part of the code is auto-generated ? – phramusca May 19 '11 at 20:01
  • I'm not familiar with the netbeans auto generation tools. Generally static references to classes in Swing is a bad idea. Again its hard to say for sure without seeing the entire classes as opposed to snipits of code but you either need to save the reference to the JPanel outside of the block so it can be passed to the button action or provide some sort of getter for it – meverett May 19 '11 at 20:12
  • I found out the solution, thanks to you guys. I needed to add my extended class as a Swing component in NetBeans Swing palette and use it from the palette, so the auto-generated code can declare the jPanel with the good type: How to add the code to palette found here: http://forums.netbeans.org/topic37532.html – phramusca May 19 '11 at 20:47
  • 1
    This is one more reason to hand-code GUIs rather than using UI designers. – jfpoilpret May 19 '11 at 21:02
  • Right Click on component, and select, Customize code, and then do the editing. Additionally, i copy the whole layout in Eclipse and from that base start tweaking it – Johnydep Feb 04 '12 at 03:37
0

Just define this JPanel variable: lp2_2

And then set the image to this JPanel in the following manner:

lp2_2.setIcon(new ImageIcon((new ImageIcon("tank.jpg")).getImage().getScaledInstance( 600, 600,  java.awt.Image.SCALE_SMOOTH )));   
Gherbi Hicham
  • 2,416
  • 4
  • 26
  • 41
abhilash_goyal
  • 711
  • 1
  • 10
  • 31