【问题标题】:Unable to draw a simple image using JComponent无法使用 JComponent 绘制简单图像
【发布时间】:2011-10-16 14:40:06
【问题描述】:

我正在使用 netbeans IDE 来练习一些 Java 基本代码。但是我没有成功绘制PNG图像。下面是我的代码,

package JavaApplication1;

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

class MyCanvas extends JComponent
{
    Image img;
    public MyCanvas(){
        img = Toolkit.getDefaultToolkit().createImage("pengbrew.png");
    }

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

public class JavaGame
{
    public static void main(String args[]){
        JFrame window = new JFrame("Image demo");
        window.getContentPane().add( new MyCanvas() );
        window.setSize(400,400);
        window.setVisible(true);
    }
}

我在 netbeans 项目中添加了图像。

请指教。

非常感谢。

【问题讨论】:

  • 可能是因为您保存 PNG 图片的位置。
  • Raze 可能总结了您的问题。你的图像与你的类文件在哪里?它们与您的用户目录(Java 当前正在查找图像的位置)的关系在哪里?

标签: image swing java imageicon


【解决方案1】:

最简单的方法是查找JLabel,这是JComponents 中最好的Icon/ImageIcon 示例here

【讨论】:

    【解决方案2】:

    要加载图像,请使用ImageIO.read(File file)。这是一个更新的 API,更易于使用且得到更好的支持。如果您需要更多指针,这里有一个关于加载图像的教程http://docs.oracle.com/javase/tutorial/2d/images/loadimage.html

    您的代码应该是这样的,

    Image img;
    public MyCanvas(){
        try {
            img = ImageIO.read(new File("pengbrew.png"));
        } catch (IOException e) {
            // Handle exception if there is one.
        }
    }
    

    关于为什么您使用的方法不起作用的长答案可能是因为以下...

    您的图像可能位于正确的位置,但 Toolkit.createImage() 尚未在帧开始绘制之前完成加载图像。 Toolkit.createImage() 在底层图像实际完成加载之前将控制权返回给您的应用程序。您通常可以通过调整应用程序的大小来强制它重新绘制来验证这是否是问题所在。如果在尝试调整应用程序大小几秒钟后显示图像,那是由于在第一次绘制调用期间未加载图像。

    要确保在继续之前加载图像,您需要使用 MediaTracker。这是一些示例代码,以确保在使用之前完成图像的加载。

    Component component = new Component() {};
    MediaTracker TRACKER = new MediaTracker(component);
    
    ...
    
    Image image = Toolkit.getDefaultToolkit().createImage("imageToLoad.png");
    synchronized(TRACKER) {
       int id = ++mediaTrackerID;
       TRACKER.addImage(image, id);
       try {
           TRACKER.waitForID(id, 0);
       } catch (InterruptedException ex) {
           image = null;
       }
       TRACKER.removeImage(image, id);
    }
    // Now you can use your image.
    

    您将在 ImageIcon 类的 loadImage(Image image) 方法中看到类似这样的代码。

    【讨论】:

    • 也可以考虑ImageIO.read(),提到here
    • 请记住,这两种方法之间存在性能差异。 ImageIO 比使用 MediaTracker 慢,但 ImageIO 是较新的 API,使用起来更多更好。我只是希望 Oracle 能提高它的性能。
    • IIUC, ImageIO 有固定延迟;是不是也比较慢?
    • @trashgod 我编写了一个简单的测试来从文件加载 jpeg 并打印出使用媒体跟踪器和 ImageIO 加载的时间。当我加载 129k jpg 时,媒体跟踪器方法至少快 2 倍。几年前我用较小的文件完成了这项工作,但没有数字。如果您有兴趣,非常乐意在某处发布我的性能测试用例。
    • 完成。为了完整起见,我保留了原始答案,但将 ImageIO 实现放在首位。如果您认为我应该删除媒体跟踪器部分,请告诉我。再次感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多