使用ImageIcon 可能是最直接的做法。有几点要记住:
因此,您的问题可能不是使用 Toolkit(ImageIO 是另一种野兽),而是您没有渲染完全加载的图像这一事实。一件有趣的事情是:
Image image = f.getToolkit().createImage(url);
//...
ImagePanel imagePanel = new ImagePanel(image);
imagePanel.prepareImage(image, imagePanel);
//...
我的 Swing/AWT/J2D 可能有点模糊,但想法是,由于您的 ImagePanel 是 ImageObserver,因此可以异步通知图像信息。 Component.imageUpdate() 方法应根据需要调用 repaint。
编辑:
如 cmets 中所述,不需要调用 prepareImage - 下面包含一个工作示例。关键是重写的paintComponent 方法调用了Graphics.drawImage,它提供了ImageObserver 钩子。 imageUpdate 方法(在java.awt.Component 中实现)将在设置ImageObserver.FRAMEBITS 标志的情况下不断被调用。
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class ImagePanel extends JPanel {
private final Image image;
public ImagePanel(Image image) {
super();
this.image = image;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(this.image, 0, 0, getWidth(), getHeight(), this);
}
public static void main(String[] args) throws MalformedURLException {
final URL url = new URL("http://i.stack.imgur.com/iQFxo.gif");
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("Image");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
Image image = f.getToolkit().createImage(url);
ImagePanel imagePanel = new ImagePanel(image);
imagePanel.setLayout(new GridLayout(5, 10, 10, 10));
imagePanel.setBorder(new EmptyBorder(20, 20, 20, 20));
for (int ii = 1; ii < 51; ii++) {
imagePanel.add(new JButton("" + ii));
}
f.setContentPane(imagePanel);
f.pack();
f.setVisible(true);
}
});
}
}