Java 如何将图像添加到 JPanel?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/299495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:47:10  来源:igfitidea点击:

How to add an image to a JPanel?

javaimageswingjpanel

提问by Leonel

I have a JPanelto which I'd like to add JPEG and PNG images that I generate on the fly.

我有一个JPanel,我想向其中添加即时生成的 JPEG 和 PNG 图像。

All the examples I've seen so far in the Swing Tutorials, specially in the Swing examplesuse ImageIcons.

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

I'm generating these images as byte arrays, and they are usually larger than the common icon they use in the examples, at 640x480.

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

  1. Is there any (performance or other) problem in using the ImageIcon class to display an image that size in a JPanel?
  2. What's the usualway of doing it?
  3. How to add an image to a JPanel without using the ImageIcon class?
  1. 使用 ImageIcon 类在 JPanel 中显示该大小的图像是否有任何(性能或其他)问题?
  2. 什么是平常做的呢?
  3. 如何在不使用 ImageIcon 类的情况下将图像添加到 JPanel?

Edit: A more careful examination of the tutorials and the API shows that you cannot add an ImageIcon directly to a JPanel. Instead, they achieve the same effect by setting the image as an icon of a JLabel. This just doesn't feel right...

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

采纳答案by Brendan Cashman

Here's how I do it (with a little more info on how to load an image):

这是我的操作方法(有关如何加载图像的更多信息):

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            
    }

}

回答by Lawrence Dol

You can subclass JPanel - here is an extract from my ImagePanel, which puts an image in any one of 5 locations, top/left, top/right, middle/middle, bottom/left or bottom/right:

您可以将 JPanel 子类化 - 这是我的 ImagePanel 的摘录,它将图像放在 5 个位置中的任何一个,上/左、上/右、中/中、下/左或下/右:

protected void paintComponent(Graphics gc) {
    super.paintComponent(gc);

    Dimension                           cs=getSize();                           // component size

    gc=gc.create();
    gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
    if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2)       +mmHrzShift),(((cs.height-mmSize.height)/2)        +mmVrtShift),null); }
    if(tlImage!=null) { gc.drawImage(tlImage,(insets.left                       +tlHrzShift),(insets.top                           +tlVrtShift),null); }
    if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top                           +trVrtShift),null); }
    if(blImage!=null) { gc.drawImage(blImage,(insets.left                       +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
    if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
    }

回答by Michael Myers

  1. There shouldn't be any problem (other than any general problems you might have with very large images).
  2. If you're talking about adding multiple images to a single panel, I would use ImageIcons. For a single image, I would think about making a custom subclass of JPaneland overriding its paintComponentmethod to draw the image.
  3. (see 2)
  1. 应该没有任何问题(除了非常大的图像可能会遇到的任何一般问题)。
  2. 如果您正在谈论将多个图像添加到单个面板,我会使用ImageIcons。对于单个图像,我会考虑创建一个自定义子类JPanel并覆盖其paintComponent绘制图像的方法。
  3. (见2)

回答by Tom Hawtin - tackline

JPanelis almost always the wrong class to subclass. Why wouldn't you subclass JComponent?

JPanel几乎总是错误的类到子类。你为什么不子类JComponent

There is a slight problem with ImageIconin that the constructor blocks reading the image. Not really a problem when loading from the application jar, but maybe if you're potentially reading over a network connection. There's plenty of AWT-era examples of using MediaTracker, ImageObserverand friends, even in the JDK demos.

ImageIcon构造函数阻止读取图像有一个小问题。从应用程序 jar 加载时并不是真正的问题,但也许如果您可能通过网络连接进行读取。即使在 JDK 演示中,也有很多 AWT 时代使用MediaTracker,ImageObserver和朋友的例子。

回答by Thomas Jones-Low

I'm doing something very similar in a private project I'm working on. Thus far I've generated images up to 1024x1024 without any problems (except memory) and can display them very quickly and without any performance problems.

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

Overriding the paint method of JPanel subclass is overkill and requires more work than you need to do.

覆盖 JPanel 子类的paint方法是过度的,需要做的工作比你需要做的更多。

The way I do it is:

我这样做的方式是:

Class MapIcon implements Icon {...}

OR

或者

Class MapIcon extends ImageIcon {...}

The code you use to generate the image will be in this class. I use a BufferedImage to draw onto then when the paintIcon() is called, use g.drawImvge(bufferedImage); This reduces the amount of flashing done while you generate your images, and you can thread it.

您用于生成图像的代码将在此类中。当调用paintIcon() 时,我使用BufferedImage 进行绘制,使用g.drawImvge(bufferedImage); 这减少了生成图像时完成的闪烁量,并且您可以将其串接起来。

Next I extend JLabel:

接下来我扩展 JLabel:

Class MapLabel extends Scrollable, MouseMotionListener {...}

This is because I want to put my image on a scroll pane, I.e. display part of the image and have the user scroll around as needed.

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

So then I use a JScrollPane to hold the MapLabel, which contains only the MapIcon.

那么我使用 JScrollPane 来保存 MapLabel,它只包含 MapIcon。

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

scrollPane.getViewport ().add (mapLabel);

But for your scenario (just show the whole image every time). You need to add the MapLabel to the top JPanel, and make sure to size them all to the full size of the image (by overriding the GetPreferredSize()).

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

回答by Dan Vinton

You can avoid rolling your own Component subclass completely by using the JXImagePanel class from the free SwingXlibraries.

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

Download

下载

回答by CoderTim

I think there is no need to subclass of anything. Just use a Jlabel. You can set an image into a Jlabel. So, resize the Jlabel then fill it with an image. Its OK. This is the way I do.

我认为没有必要对任何东西进行子类化。只需使用 Jlabel。您可以将图像设置为 Jlabel。因此,调整 Jlabel 的大小,然后用图像填充它。没关系。这就是我的做法。

回答by Fred Haslam

If you are using JPanels, then are probably working with Swing. Try this:

如果您使用的是 JPanels,那么可能正在使用 Swing。尝试这个:

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

The image is now a swing component. It becomes subject to layout conditions like any other component.

图像现在是一个摆动组件。它会像任何其他组件一样受到布局条件的影响。

回答by shawalli

Fred Haslam's way works fine. I had trouble with the filepath though, since I want to reference an image within my jar. To do this, I used:

弗雷德哈斯拉姆的方式工作正常。不过,我在文件路径方面遇到了问题,因为我想在我的 jar 中引用一个图像。为此,我使用了:

BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));

Since I only have a finite number (about 10) images that I need to load using this method, it works quite well. It gets file without having to have the correct relative filepath.

由于我只有有限数量(大约 10 个)需要使用此方法加载的图像,因此它运行良好。它无需具有正确的相对文件路径即可获取文件。

回答by shawalli

JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));