1

我有一个相当简单的绘图程序,它使用 BufferedImage 作为画布。我有一个单独的类 ( IOClass) 来处理保存图像和打开另一个图像。我在通过我的saveImage()方法保存 BufferedImage 时遇到了一些麻烦。这是整个班级:

 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);

    }
}

因此,正如您通过阅读该saveImage()方法所看到的那样,这就是问题所在。程序打开,你画了一张图片,你进入带有“另存为”菜单选项的 JMenuBar,它激活了一个 actionListener,它打开了这个类并启动了 new fileChooser,你可以在其中使用 JFileChooser 保存图像。图像拒绝保存,而是引发 IllegalArguementException。问题必须出在这个 Save 方法中,我假设它发生在ImageIO.write(bla bla bla)方法中。我该怎么做才能确保正确保存此图像,以及我到底做错了什么?我已经阅读了一点 JFileChooser API,我认为这是其中唯一真正重要的部分,但如果我应该回去添加一些东西,请告诉我。谢谢。

额外:只有当用户按下主程序的 JMenuBar 上的“另存为”按钮时,JFileChooser 才会出现(未显示)。主程序使用“Nimbus”主题,使用代码片段即可使用:

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();
        }

当我之前尝试的时候,打开 JFileChooser 时也会打开 Nimbus 主题,但现在,它只会以正常、无聊、默认的 Swing 外观打开。我能做些什么来恢复 Nimbus 主题(看起来好多了)。

编辑:根据要求,完整的堆栈跟踪:

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)
4

1 回答 1

5

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());
于 2013-06-10T00:02:14.840 回答