我有一个JPanel,我想添加我在飞行中生成的JPEG和PNG图像。

到目前为止,我在Swing教程中看到的所有示例,特别是在Swing示例中,都使用了ImageIcons。

我将这些图像生成为字节数组,它们通常比示例中使用的普通图标大,为640x480。

在使用ImageIcon类在JPanel中显示这样大小的图像时,是否存在任何(性能或其他)问题? 通常的做法是什么? 如何添加一个图像到JPanel而不使用ImageIcon类?

编辑:对教程和API进行更仔细的检查可以发现,您不能将ImageIcon直接添加到JPanel中。相反,它们通过将图像设置为JLabel的图标来实现相同的效果。这感觉不对……


当前回答

如果您正在使用jpanel,那么您可能正在使用Swing。试试这个:

BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);

图像现在是一个摆动组件。它像其他组件一样受到布局条件的制约。

其他回答

JPanel几乎总是要子类化的错误类。为什么不子类化JComponent呢?

ImageIcon有一个小问题,构造函数阻塞读取图像。当从应用程序jar中加载时,这并不是真正的问题,但如果您可能通过网络连接进行读取,则可能存在问题。在awt时代有很多使用MediaTracker、ImageObserver及其朋友的例子,甚至在JDK演示中也是如此。

你可以避免使用自己的组件和SwingX库和ImageIO类:

File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));

下面是我怎么做的(有更多关于如何加载图像的信息):

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImagePanel extends JPanel{

    private BufferedImage image;

    public ImagePanel() {
       try {                
          image = ImageIO.read(new File("image name and path"));
       } catch (IOException ex) {
            // handle exception...
       }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters            
    }

}

通过使用来自免费SwingX库的JXImagePanel类,可以避免完全滚动自己的Component子类。

下载

我在自己的一个私人项目中也在做类似的事情。到目前为止,我已经生成了高达1024x1024的图像,没有任何问题(除了内存),并且可以非常快速地显示它们,没有任何性能问题。

重写JPanel子类的paint方法是多余的,并且需要比您需要做的更多的工作。

我的做法是:

Class MapIcon implements Icon {...}

OR

Class MapIcon extends ImageIcon {...}

用于生成图像的代码将在该类中。我使用BufferedImage来绘制然后当paintIcon()被调用时,使用g.drawImvge(BufferedImage);这样可以减少生成图像时的闪烁次数,并且可以使用线程。

接下来我扩展JLabel:

Class MapLabel extends Scrollable, MouseMotionListener {...}

这是因为我想把我的图像放在滚动窗格上,即显示图像的一部分,并让用户根据需要滚动。

因此,我使用JScrollPane来保存只包含MapIcon的MapLabel。

MapIcon map = new MapIcon (); 
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();

scrollPane.getViewport ().add (mapLabel);

但对于你的场景(每次只显示整个图像)。您需要将MapLabel添加到顶部JPanel,并确保将它们全部设置为图像的完整大小(通过覆盖GetPreferredSize())。