我有一个JPanel,我想添加我动态生成的JPEG和PNG图像.
到目前为止我在Swing教程中看到的所有示例,特别是在Swing示例中使用的ImageIcon
是s.
我将这些图像生成为字节数组,并且它们通常比它们在示例中使用的常见图标大,为640x480.
使用ImageIcon类在JPanel中显示大小的图像时是否存在(性能或其他)问题?
什么是平常做的呢?
如何在不使用ImageIcon类的情况下将图像添加到JPanel?
编辑:仔细检查教程和API会显示您无法将ImageIcon直接添加到JPanel.相反,它们通过将图像设置为JLabel的图标来实现相同的效果.这感觉不对......
如果你正在使用JPanels,那么可能正在使用Swing.试试这个:
BufferedImage myPicture = ImageIO.read(new File("path-to-file")); JLabel picLabel = new JLabel(new ImageIcon(myPicture)); add(picLabel);
图像现在是摆动组件.它像任何其他组件一样受制于布局条件.
这是我如何做的(有关如何加载图像的更多信息):
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 } }
弗雷德哈斯拉姆的方式很好.我在文件路径上遇到了麻烦,因为我想在我的jar中引用一个图像.为此,我使用了:
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png")); JLabel wIcon = new JLabel(new ImageIcon(wPic));
由于我只需要使用此方法加载的有限数量(约10个)图像,因此效果非常好.它获取文件而无需具有正确的相对文件路径.
我认为不需要任何子类.只需使用Jlabel.您可以将图像设置为Jlabel.因此,调整Jlabel的大小,然后用图像填充它.没关系.这就是我的方式.
您可以通过使用免费SwingX库中的JXImagePanel类来完全避免滚动自己的Component子类.
下载
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
应该没有任何问题(除了您可能对非常大的图像有任何一般问题).
如果您正在谈论将多个图像添加到单个面板,我会使用ImageIcon
s.对于单个图像,我会考虑制作自定义子类JPanel
并覆盖其paintComponent
绘制图像的方法.
(见2)
你可以子类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); } }
JPanel
几乎总是错误的子类.你为什么不进行子类化JComponent
?
存在一个小问题,ImageIcon
即构造函数阻塞读取图像.从应用程序jar加载时不是真正的问题,但也许你可能通过网络连接阅读.有大量的使用AWT时代的例子MediaTracker
,ImageObserver
和朋友,甚至在JDK演示.
我正在做一个我正在做的私人项目中做类似的事情.到目前为止,我已经生成了高达1024x1024的图像,没有任何问题(内存除外),并且可以非常快速地显示它们而没有任何性能问题.
覆盖JPanel子类的paint方法是过度的,需要比你需要做的更多的工作.
我这样做的方式是:
Class MapIcon implements Icon {...}
要么
Class MapIcon extends ImageIcon {...}
用于生成图像的代码将在此类中.我使用BufferedImage绘制到当时调用paintIcon()时,使用g.drawImvge(bufferedImage); 这样可以减少生成图像时完成的闪烁次数,并且可以对其进行处理.
接下来我扩展JLabel:
Class MapLabel extends Scrollable, MouseMotionListener {...}
这是因为我想将我的图像放在滚动窗格上,即显示图像的一部分并让用户根据需要滚动.
那么我使用JScrollPane来保存MapLabel,它只包含MapIcon.
MapIcon map = new MapIcon (); MapLabel mapLabel = new MapLabel (map); JScrollPane scrollPane = new JScrollPane(); scrollPane.getViewport ().add (mapLabel);
但对于您的场景(每次只显示整个图像).您需要将MapLabel添加到顶部JPanel,并确保将它们全部调整为图像的完整大小(通过重写GetPreferredSize()).
在您的项目目录中创建一个源文件夹,在这种情况下,我将其称为“图像”。
JFrame snakeFrame = new JFrame(); snakeFrame.setBounds(100, 200, 800, 800); snakeFrame.setVisible(true); snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png"))); snakeFrame.pack();