Search code examples
javaswingbufferedimagejfilechoosernimbus

Saving a BufferedImage using a JFileChooser raises a few problems


I have a fairly simply paint program that uses a BufferedImage as a canvas. I have a separate class (IOClass) that handles saving the image and opening another image. I'm having a bit of trouble saving the BufferedImage through my saveImage() method. Here's the entire class:

 package ui;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

// class for Saving & Opening images (for the bufferedImage called 'background'
public class IOClass {
    static BufferedImage image;

    public IOClass(BufferedImage image) {
        this.image = image;
    }

    public static final JFileChooser fileChooser = new JFileChooser();
    public void saveImage() {
        int saveValue = fileChooser.showSaveDialog(null);
        if (saveValue == JFileChooser.APPROVE_OPTION) {
            try {
                ImageIO.write(image, "png", new File(fileChooser
                        .getSelectedFile().getAbsolutePath()
                        + fileChooser.getSelectedFile().getName()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public BufferedImage openImage() {
        int open = fileChooser.showOpenDialog(null);

    }
}

So, as you can see by reading the saveImage() method, this is where the problem is. The program opens up, you draw a picture, you go to the JMenuBar with the 'Save As' menu option, which activates an actionListener that opens this class and initiates the new fileChooser, where you can save the image using the JFileChooser. The image refuses to save and instead raises an IllegalArguementException. The problem has to be in this Save method, and I'm assuming it happens in the the ImageIO.write(bla bla bla) method. What can I do to make sure that this image saves correctly, and what exactly am I doing wrong? I've read a little bit of the JFileChooser API, and I thought that this was the only real essential part of this, but let me know if I should go back and add something. Thanks.

Extra: The JFileChooser comes up only when the User presses the "save as" button on the JMenuBar of the main program(not shown). The main program uses the "Nimbus" theme, which can be used by using the code piece:

try {
            UIManager
                    .setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

When I was trying something earlier, opening the JFileChooser also opened up with the Nimbus theme, but now, it only opens with the normal, boring, default Swing look. What can I do to bring back the Nimbus theme (it looks a lot better).

EDIT: As requested, the full stack trace:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: image == null!
    at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(Unknown Source)
    at javax.imageio.ImageIO.getWriter(Unknown Source)
    at javax.imageio.ImageIO.write(Unknown Source)
    at ui.IOClass.saveImage(IOClass.java:26)
    at ui.ProgramUI$saveAsListener.actionPerformed(ProgramUI.java:406)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.AbstractButton.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

Solution

  • Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: image == null!

    The exception states that it is being thrown because your image is null, so the problem is not in the code above, but in the code that calls the code above: You're passing in a null image.

    To prove it one way or the other, test it:

        if (saveValue == JFileChooser.APPROVE_OPTION) {
          System.out.println("is image null? " + (image == null));
          try {
            // ....
    

    Also and again, these guys:

    static BufferedImage image;
    public static final JFileChooser fileChooser = new JFileChooser();
    

    should not be static. Again, the JFileChooser likely loses the Nimbus L&F because of this, because it is initiated when the class loads, before you've set the L&F, and not when an object of your IOClass is instantiated.


    Edit
    As an aside, shouldn't this:

    ImageIO.write(image, "png", new File(fileChooser
                        .getSelectedFile().getAbsolutePath()
                        + fileChooser.getSelectedFile().getName()));
    

    be this?:

    ImageIO.write(image, "png", fileChooser.getSelectedFile());