在Java中无法显示ImageIcon

3

这段代码本应该显示一个背景图片和玩家,但实际上只显示了一个粉色的屏幕。我无法确定问题出在哪里,请看我的代码。

package main;

import java.awt.*;
import javax.swing.ImageIcon;    
import javax.swing.JFrame;

public class Images extends JFrame {

    public static void main(String Args[]) {

        DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN); // This is going to take 4 parameter, first 2 is x and y for resolotion. Bit depth, the number of bits in a cloour
                                                                                            // 16 is your bit depth. the last one is the monitor refresh, it means it will refres how much it wants
        Images i = new Images(); // making an object for this class
        i.run(dm); // making a run method and is taking the dm as a parameter, in this method we are putting stuff on the screen.
    }

    private Screen s; // Creating the Screen, from the Screen.java
    private Image bg; // Background
    private Image pic; // Face icon
    private boolean loaded; // Making the loaded

    //Run method
    private void run(DisplayMode dm) { // this is where we do things for the screen
        setBackground(Color.PINK); // Setting the Background
        setForeground(Color.WHITE); // Setting the ForeGround
        setFont(new Font("Arial", Font.PLAIN, 24)); // setting the font

        s = new Screen(); // now we can call ALL methods from the Screen object
        try {
            s.setFullScreen(dm, this); // This is setting the full screen, it takes in 2 parameters, dm is the display mode, so its setting the display settings, the next part is the this, what is just s, the screen object.
            loadpics(); // calling the loadpics method
            try { // so if that try block works, then it will put it to sleep for 5 seconds
                Thread.sleep(5000); // its doing this because, at the bottom (s.restorescreen) this makes it into a window again. so it needs to show it for 5 seconds.
            } catch (Exception ex) {
            }
        } finally {
            s.restoreScreen();
        }
    }

    // Loads Pictures
    private void loadpics() {
        System.out.println("Loadpics == true");
        bg = new ImageIcon("Users/georgebastow/Picture/background.jpg").getImage(); // Gets the background
        pic = new ImageIcon("Users/georgebastow/Picture/Player.png").getImage(); // Gets the Player
        System.out.println("Loaded == true in da future!");
        loaded = true; // If the pics are loaded then...    
    }

    public void paint(Graphics g) {
        if (g instanceof Graphics2D) { // This has to happen, its saying if g is in the class Graphics2D, so if we have the latest version of java, then this will run 
            Graphics2D g2 = (Graphics2D) g; // Were making the Text smooth but we can only do it on a graphcis2D object.
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // we are making the text aniti alias and turning it on!(it means making the text smooths! :) )
        }
        if(loaded == true){
            System.out.println("Loaded == true3");
            g.drawImage(bg,0,0,null);
            g.drawImage(pic, 170, 180, null);
            System.out.println("Loaded == true4");
        }
    }    
}

在此提前非常感谢你。
2个回答

8
使用图像时,应通过URL加载它们,使用Class.getResource()方法返回一个URL。如果将String传递给ImageIcon,则会导致查找文件系统中的图像。虽然在开发IDE期间这可能有效,但你会发现在部署时无法正常工作。最好现在进行更改。使用此方法,你需要这样做。
ImageIcon icon = new ImageIcon(Images.class.getResource("/Users/georgebastow/Picture/background.jpg"));

为了使此功能正常工作,您的文件结构需要如下所示。
ProjectRoot
          src
             Users
                  georgebastow
                            Picture
                                  background.jpg

一种更常见的方法是将图片放在资源文件夹中,使用src引用。
ProjectRoot
          src
             resources
                     background.jpg

并使用这个路径

ImageIcon icon = new ImageIcon(Images.class.getResource("/resources/background.jpg"));                     

当您进行构建时,IDE将把图片转移到类路径中。


附注

  • Don't paint on top level containers like JFrame. Instead use JPanel or JComponent and override the paintComponent method. if using JPanel, you should also call super.paintComponent in the paintComponent method.
  • Run you Swing Apps from the Event Dispatch Thread like this

    public static void main(String[] args) {
        SwingUtiliities.invokeLater(new Runnable(){
            public void run() {
                new Images();
            }
        });
    }
    

    See Initial Thread

  • Don't call Thread.sleep(). When running from the EDT (like you should), you will block it. Instead use a java.swing.Timer if it's animation you're looking for. Even if it's not animation, still use it! See this example for Timer program.

  • Also as @mKorbel mentioned, you never add anything to the frame.

更新

运行这个例子。我还忘了提到,当你在JPanel上绘制时,也要重写getPreferredSize()。这将给你的面板一个大小。

src/resources/stackoverflow5.png

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestImage {

    public TestImage() {
        JFrame frame = new JFrame("Test Image");
        frame.add(new NewImagePanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public class NewImagePanel extends JPanel {

        private BufferedImage img;

        public NewImagePanel() {
            try {
                img = ImageIO.read(TestImage.class.getResource("/resources/stackoverflow5.png"));
            } catch (IOException ex) {
                System.out.println("Could not load image");
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestImage();
            }
        });
    }
}

ImageIcon实例化的末尾,您需要像之前一样使用.getImage()。确保将bg保留为无法绘制的ImageImageIcon - Paul Samsotha
我已经完成了这个程序,但运行时它没有显示图像。为什么会发生这种情况呢?整个屏幕都显示成粉色。 - Pilkin
我正在使用Mac OS X,屏幕在第一秒钟就退出全屏模式,所以Dock会显示出来。 - Pilkin
使用 bg = ImageIO.read(Images.class.getResource("/res/background.jpg"); 并将其包装在 try/catch 块中。如果图像未加载,则说明路径错误。如果没有抛出异常,则问题可能出在其他地方。 - Paul Samsotha
我遇到了这个错误:线程"AWT-EventQueue-0"中的异常java.lang.IllegalArgumentException: input == null! 在javax.imageio.ImageIO.read(ImageIO.java:1388)处 在main.TestImage$NewImagePanel.<init>(TestImage.java:28)处 在main.TestImage.<init>(TestImage.java:16)处 在main.TestImage$1.run(TestImage.java:50)处 ...后面的内容太长了,无法显示 - Pilkin
显示剩余12条评论

3
  1. JFrame不是用于显示Image的合适组件(它的容器)

  2. 对于JFrame,使用paint()方法不是显示图像或自定义绘画、图形的正确方式

  3. 如果没有在JFrame中使用任何JComponent或有/没有JComponent,则可以使用带有setIcon()JLabel

  4. 如果将JPanel用作其他JComponent的容器,则应该将其放置在JFrame.CENTER区域,并覆盖paintComponent(而不是paint

  5. 更多信息请参见Oracle教程:使用图像


谢谢mKorbel,我想在不使用JFrame的情况下运行paint。我该如何在没有JFrame的情况下进行绘制?我应该使用什么替代品? - Pilkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接