【问题标题】:Adding image to JPanel through ImageIO.read?通过 ImageIO.read 将图像添加到 JPanel?
【发布时间】:2011-12-28 04:51:18
【问题描述】:

我正在尝试添加一个带有图片的 JPanel。我正在使用 ImageIO.read 来获取路径,但我得到一个 IOException 说:无法读取输入文件

图片名为TCHLogo。这是我项目中“res”文件夹中的 PNG。

如果有更好的方式来展示这张图片,也请提出来!

这是我的 JPanel 的代码:

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() {
        try {                
           //THIS LINE BELLOW WAS ADDED
           image = ImageIO.read(getClass().getResourceAsStream("res/TCHLogo.png"));
        } catch (IOException ex) {
             // handle exception...
            System.out.println(ex);
        }
     }

     @Override
     public void paintComponent(Graphics g) {
         super.paintComponent(g);  //THIS LINE WAS ADDED
         g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters
     }

}

这是我在 Applet 中添加 JPanel 的方法:

ImagePanel appletRunningPanel;
appletRunningPanel = new ImagePanel();
appletRunningPanel.setSize(300, 300);
appletRunningPanel.validate();
add(appletRunningPanel);

编辑 我在应用程序当前开始查找的 bin 内创建了一个文件夹。 文件夹叫 res 里面有图片..

现在我在运行该行时得到以下 IOException:

image = ImageIO.read(getClass().getResourceAsStream("res/TCHLogo.png"));

这是错误日志:

java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(ImageIO.java:1338)
    at surprice.applet.ImagePanel.<init>(ImagePanel.java:17)
    at surprice.applet.MainClass.init(MainClass.java:41)
    at sun.applet.AppletPanel.run(AppletPanel.java:436)
    at java.lang.Thread.run(Thread.java:679)

【问题讨论】:

    标签: java swing io jpanel paintcomponent


    【解决方案1】:

    可能您的图像文件路径相对于用户目录不正确。要找出 Java 开始查找的位置、用户目录的位置,请在程序中的某处放置类似这行代码:

    System.out.println(System.getProperty("user.dir"));
    

    也许您最好将图像作为从资源获取的 InputStream 而不是作为文件获取。例如,

    image = ImageIO.read(getClass().getResourceAsStream("res/TCHLogo.png"));
    

    这将在相对于类文件位置的路径中查找图像,事实上,如果图像位于 jar 文件中,这是您必须执行的操作。

    编辑 2
    顺便说一句,在进行任何自己的绘图之前,您通常需要先调用 super 的 paintComponent 方法,以便可以进行必要的内部维护,例如摆脱“脏”图像位。例如,改变这个:

     public void paintComponent(Graphics g) {
         g.drawImage(image, 0, 0, null); 
     }
    

    到这里:

     public void paintComponent(Graphics g) {
         super.paintComponent(g); // **** added****
         g.drawImage(image, 0, 0, null); 
     }
    

    【讨论】:

    • 它开始在工作区/Applet/bin 中查找。也许我可以在项目的 bin 文件夹中创建一个文件夹。但是当我导出它时,这些图像也会在 .jar 文件中吗?
    • @TheCompBoy:如果你把它们放在罐子里,它们就会在罐子里。你用什么来编辑你的程序,一个IDE?如果有很多向导可以帮助您创建 jar 文件并添加选定的文件和资源。
    • 当我尝试使用您的代码行时 (image=ImageIO.read(getClass().getResourceAsStream("res/TCHLogo.png"));) 我收到此错误消息:java.lang .IllegalArgumentException:输入 == 空!在 javax.imageio.ImageIO.read(ImageIO.java:1338) 在 surprice.applet.ImagePanel.(ImagePanel.java:17) 在 surprice.applet.MainClass.init(MainClass.java:41) 在太阳。 applet.AppletPanel.run(AppletPanel.java:436) 在 java.lang.Thread.run(Thread.java:679)
    • @TheCompBoy:你的图像文件相对于你的类文件在哪里?
    • @TheCompBoy 我已经通过使用getClass().getClassLoader().getResourceAsStream(path) 解决了类似的问题
    【解决方案2】:

    我已经编写了这个用于这个范围的 ImagePanel 类:

    public class ImagePanel extends JPanel {
    
        private static final long serialVersionUID = 7952119619331504986L;
        private BufferedImage image;
    
        public ImagePanel() { }
    
        public ImagePanel(String resName) throws IOException {
            loadFromResource(resName);
        }
    
        public ImagePanel(BufferedImage image) {
            this.image = image;
         }
    
        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters
    
        }
    
        public BufferedImage getImage() {
            return image;
        }
    
        public void setImage(BufferedImage image) {
            this.image = image;
        }
    
        /**
         * Load the Image from a File
         * @param path image name and path
         * @throws IOException
         */
        public void loadFromFile(String path) throws IOException {
            image = ImageIO.read(new java.io.File(path));
        }
    
        /**
         * Load Image from resource item
         * @param resName name of the resource (e.g. : image.png)
         * @throws IOException
         */
        public void loadFromResource(String resName) throws IOException { 
            URL url = this.getClass().getResource(resName);
            BufferedImage img = ImageIO.read(url);
    
            image = img;
        }
    }
    

    然后我以这种方式使用 ImagePanel:

     //Inizialization of the ImagePanel
     ImagePanel panelImage = new ImagePanel();
    //Try loading image into the image panel
            try {
                panelImage.loadFromResource("/Resources/someimage.png");
            } catch (java.io.IOException e) {
                    //Handling Exception
            }
    

    【讨论】:

    • 按原样,您的paintComponent 实现无效:默认情况下,JPanel 报告为不透明 - 因此它保证填充每个像素。另外:它应该实现 getXXSize 以使 LayoutManagers 的生活更轻松:-)
    猜你喜欢
    • 2012-07-12
    • 1970-01-01
    • 2017-09-07
    • 2010-09-22
    • 2013-12-16
    相关资源
    最近更新 更多