【问题标题】:How do I display a BufferedImage in a JComponent?如何在 JComponent 中显示 BufferedImage?
【发布时间】:2020-07-17 08:32:02
【问题描述】:

我已经尝试了好几个小时了。我有一个扩展 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);


    }
}

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

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

【问题讨论】:

  • 考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个例子,它突出了您遇到的问题。这将减少混乱并获得更好的响应
  • 请注意paintComponent 会经常被称为非常。因此,在那里做一些耗时的事情(比如读取图像文件)并不是一个好主意
  • JLabel 有什么问题?
  • 对于exampleexample
  • 我测试了你的代码变体,它对我来说很好

标签: java swing bufferedimage jcomponent


【解决方案1】:

请注意,您的JComponent 每秒可能会被绘制数百次, 例如,当它被另一个移动窗口部分遮挡时。 所以,paint 方法的性能很重要,否则你会得到一个“滞后”的 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);

【讨论】:

  • 我添加了这个以使组件具有适当的大小:@Transient() @Override public Dimension getPreferredSize() { return new Dimension(200, 200); }
【解决方案2】:
Graphics g = main.getGraphics();
main.paint(g);

不,不,不,不,不!无限次NO!这不是绘画的工作原理!

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

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

手动调用paint 从来没有充分的理由,只是不要这样做。

你应该做更多的事情

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

加载图片

【讨论】:

  • 好吧,我不明白的是,你覆盖了paintComponent,但据我所知,它永远不会被调用。还是有别的东西自动调用它?
  • 请参阅 Painting in AWT and SwingPerforming Custom Painting 了解更多关于如何在 Swing 中进行绘画的详细信息
  • 谁能解释下票的原因?由于该问题没有收到任何新的否决票或任何新的关闭投票,因此不能导致该问题无效。由于其他答案都没有收到反对票(并且未能解决问题),我只能假设您对我有个人仇恨和/或实际上并不了解问题/问题和答案
  • 也许你的形象不如你个人资料中的企鹅那么性感:P(1+ 表示图片和很好的解释)
  • 好多了。异议已删除。
【解决方案3】:

试试这个:

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

【讨论】:

    【解决方案4】:

    试试这个

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

    read 抛出更多异常

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

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

    【讨论】:

    • “它没有抛出任何异常” - 表明图像已加载并且使用 FileInputStream 工作正常 - ImageIO.read(InputStream)
    • “它没有抛出任何异常” - 建议图像已加载:检查您的文件
    猜你喜欢
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多