如何在JComponent中显示BufferedImage?

时间:2017-01-27 22:10:49

标签: java swing bufferedimage jcomponent

我已经尝试了几个小时了。我有一个扩展JComponent的类,在我的paintComponent中我试图绘制一个图像,但我无法做到。这是我的代码:

public class Main extends JComponent{



public static void main(String[] args) {

    Main main = new Main();

    JFrame frame = new JFrame(Info.getGameTitle());
    frame.add(main);

    frame.setSize(Info.getWidth(), Info.getHeight());
    frame.setResizable(false);

    frame.addWindowListener(new WindowAdapter(){
        public void windowClosing(WindowEvent e){
            System.out.println("Window closed");
            System.exit(0);
        }
    });

    frame.setAlwaysOnTop(true);
    frame.setFocusable(true);
    frame.setAutoRequestFocus(true);
    frame.setLocationRelativeTo(null);

    frame.setVisible(true);

    Graphics g = main.getGraphics();

    main.paint(g);


}

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    BufferedImage image = null;
    try {
        image = ImageIO.read(new FileInputStream("images/01.jpg"));
    }catch(FileNotFoundException e) {
        System.out.println("Could not find file!");
        e.printStackTrace();
    }catch(IOException e) {
        System.out.println("Could not read file!");
        e.printStackTrace();
    } 

    g.drawImage(image, 0, 0, this);


    }
}

不会抛出任何异常,因此图像似乎已加载。但是,屏幕上没有任何内容。如果我尝试绘制形状或文本,那很好。 我做错了什么?

编辑:现在我提供了一个工作示例。

4 个答案:

答案 0 :(得分:1)

Graphics g = main.getGraphics();
main.paint(g);

不,不,不,不,不!无限次!这不是绘画的作用!

请查看Performing Custom PaintingPainting in AWT and Swing,以便更好地了解绘画在Swing中的工作原理。

getGraphics可以返回null并且只返回上次使用的上下文来绘制组件,绘制到它的任何内容都将在下一个绘制周期中被删除。

没有充分的理由手动拨打paint,只是不要这样做。

你应该做更多的事情

Example output

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img = null;

        public TestPane() {
            try {
                img = ImageIO.read(new FileInputStream("..."));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (img != null) {
                g2d.drawImage(img, 0, 0, this);
            }
            g2d.dispose();
        }

    }
}

如果您的图像仍未显示,我怀疑图像放错了位置。

new FileInputStream("images/01.jpg")

建议图像位于执行程序的当前目录中,这并不总是与程序所在的位置相同。

您可以使用System.getProperty("user.dir")来确定当前"工作"目录并将其与您认为程序所在的位置进行比较。您也可以使用File#exists来测试文件是否存在,但是,如果是这种情况,我原本希望代码抛出IOException

更好的长期解决方案是将图像嵌入到应用程序中(通常将其包含在Jar中),这样可以消除上述问题。

在这种情况下,你需要使用......

ImageIO.read(getClass().getResource("/images/01.jpg"));

加载图片

答案 1 :(得分:0)

试试这个

   BufferedImage image = null;
    try {
        image = ImageIO.read(new File(fullpathname+"/01.jpg"));
    }catch(Exception e) {
        System.out.println("Could not read file!");
        e.printStackTrace();
    } 

public void paintComponent(Graphics g) {
    super.paintComponent(g);


    g.drawImage(image, 0, 0, this);


}

阅读引发更多例外

IllegalArgumentException - if input is null.
IOException - if an error occurs during reading.

所以抓住更一般的(例外)将覆盖它

答案 2 :(得分:0)

试试这个:

Image image = ImageIO.read(new File(file)); g.drawImage(image,0,0,this);

答案 3 :(得分:0)

请注意,您的JComponent每秒可能被涂抹数百次, 例如,当它被另一个移动窗口部分遮挡时。 因此,paint方法的表现很重要,否则你会得到一个“慢慢地”#34; GUI。

因此我建议将耗时的部分(即读取图像文件)与JComponent分开。

public class ImageComponent extends JComponent {

    private BufferedImage image;

    public void setImage(final BufferedImage image) {
        this.image = image;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (image != null)
            g.drawImage(image, 0, 0, this);
    }
}

您的代码中的其他位置您读取图像文件并将其设置到组件中:

BufferedImage image = null;
try {
    image = ImageIO.read(new File(fullpathname+"/01.jpg"));
}catch(Exception e) {
    System.out.println("Could not read file!");
    e.printStackTrace();
} 
ImageComponent component = new ImageComponent();
component.setImage(image);