如何在Jpanel上添加图片?
我有一个JPNEL,我想在其中添加我即时生成的JPEG和PNG图像。
到目前为止,我在Swing Tutorials中看到的所有例子,特别是在Swing examples中都使用了`ImageIcon's。
我把这些图像生成为字节数组,它们通常比例子中使用的普通图标大,为640x480。
1.使用ImageIcon类在Jpanel中显示这么大的图像,是否有任何(性能或其他)问题? 2.2.通常*的做法是什么? 3.如何在不使用ImageIcon类的情况下向Jpanel中添加图片?
编辑。对教程和API进行更仔细的检查后发现,你不能直接向Jpanel中添加ImageIcon。相反,他们通过将图像设置为JLabel的图标来达到同样的效果。这感觉不对...。
334
14
如果你使用的是JPanels,那么可能是在使用Swing。 试试这个。
图像现在是一个摆动组件。 它变得像其他组件一样受布局条件的制约。
以下是我的做法(关于如何加载图像,还有一些信息)。
Fred Haslam'的方法很好用。 但我在文件路径方面遇到了麻烦,因为我想在我的jar中引用一个图像。 要做到这一点,我使用了
由于我只有有限数量(大约10张)的图片需要用这个方法加载,所以效果很好。 它获取文件时不需要有正确的相对文件路径。
我认为没有必要对任何东西进行子类。 只要使用一个Jlabel就可以了。 你可以在Jlabel中设置一张图片。 所以,调整Jlabel的大小,然后用图片填充。 就可以了。 我是这样做的。
通过使用免费的[SwingX][1]库中的JXImagePanel类,可以完全避免滚动自己的Component子类。
下载][2]
[1]: https://swingx.java.net// [2]: http://java.net/projects/swingx/downloads
1.不应该有任何问题(除了你在处理非常大的图像时可能遇到的任何一般问题)。 2.2. 如果你想在一个面板上添加多张图片,我会使用
ImageIcon's。对于单个图像,我会考虑制作一个自定义的
JPanel'子类,并重写其`paintComponent'方法来绘制图像。 3.(见2)你可以对Jpanel进行子类化--这里是我的ImagePanel的摘录,它将图像放在5个位置中的任何一个,顶部/左边,顶部/右边,中间/中间,底部/左边或底部/右边。
我'在我的一个私人项目中正在做一些非常类似的事情。 到目前为止,我'已经生成了高达1024x1024的图像,没有任何问题(除了内存),并且可以非常快速地显示它们,没有任何性能问题。
覆盖JPanel子类的paint方法是矫枉过正的,需要做更多的工作。
我的做法是:{{5415604}}。
或
你用来生成图像的代码将在这个类中。 我使用一个BufferedImage来绘制,然后当调用paintIcon()时,使用g.drawImvge(bufferedImage)。 这样就减少了生成图像时的闪烁量,而且你可以用线程来完成。
接下来我扩展了JLabel。
这是因为我想把我的图片放在一个滚动窗格上,即 显示图像的一部分,并让用户根据需要进行滚动。
所以我使用 JScrollPane 来保存 MapLabel,其中只包含 MapIcon。
但是对于你的方案(每次都显示整个图片即可)。 你需要将MapLabel添加到顶部的JPanel中,并确保它们的大小都是图片的全尺寸(通过覆盖GetPreferredSize())。
JPanel
几乎总是错误的子类。 为什么不把JComponent
子类化呢?ImageIcon
有一个小问题,因为构造函数会阻止读取图像。 当从应用程序jar中加载时,这并不是一个真正的问题,但如果你有可能通过网络连接进行读取,则可能是一个问题。 有很多AWT时代使用MediaTracker
、ImageObserver
和朋友的例子,甚至在JDK演示中。在你的项目目录下创建一个源文件夹,在本例中我把它叫做Images。
这个答案是对@shawalli'答案的补充......
我也想在我的 jar 中引用一张图片,但我没有使用 BufferedImage,而是简单地这样做。
可以避免使用自己的 "组件 "和SwingX库以及 "ImageIO "类。
我可以看到很多答案,并没有真正解决上级的三个问题。
1)一个关于性能的词。 字节数组很可能是低效的,除非你能使用一个精确的像素字节排序,这与你的显示适配器当前的分辨率和颜色深度相匹配。
要获得最佳的绘图性能,只需将你的图像转换为BufferedImage,BufferedImage的类型与你当前的图形配置相对应。 参见 https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html 中的 createCompatibleImage。
这些图像会在绘制几次后自动缓存在显示卡内存中,无需任何编程工作(这是Swing自Java 6以来的标准),因此,实际绘制将花费微不足道的时间--如果你没有改变图像。
改变图像将伴随着主内存和GPU内存之间的额外内存传输--这很慢。 避免"重绘"。 因此,要避免用任何方式进行getPixel和setPixel。
例如,如果你正在开发一款游戏,与其将所有的游戏角色绘制到BufferedImage中,然后再绘制到JPanel中,不如将所有的角色加载为较小的BufferedImages,然后在JPanel代码中一个一个地绘制到它们的适当位置,这样就会快很多--除了用于缓存的图像的初始传输外,主内存和GPU内存之间没有额外的数据传输。
ImageIcon会在引擎盖下使用一个BufferedImage--但基本上分配一个BufferedImage与_proper_图形模式是关键,没有努力去做好这一点。
2)通常的做法是在JPanel的重载paintComponent方法中绘制BufferedImage。 虽然Java支持大量额外的好东西,比如控制GPU内存中缓存的VolatileImages的缓冲链,但自Java 6以来,没有必要使用这些东西,它在不暴露GPU加速的所有这些细节的情况下做得相当好。
注意,GPU加速可能对某些操作不起作用,比如拉伸半透明图像。
3)不要添加。 按上面提到的画法画就可以了。
"添加"。 如果图像是布局的一部分,那就有意义了。 如果你需要将其作为填充JPanel的背景或前景图像,只需在paintComponent中绘制即可。 如果你喜欢酝酿一个通用的Swing组件,它可以显示你的图像,那么它是同样的故事(你可以使用一个JComponent,并覆盖它的paintComponent方法)--然后将_这个_添加到你的GUI组件布局中。
4)如何将数组转换为Bufferedimage(缓冲图像)
将你的字节数组转换为PNG,然后加载它是相当耗费资源的。 一个更好的方法是将现有的字节数组转换为BufferedImage。
为此。 不要使用for循环_和复制像素。 那是非常非常慢的。 取而代之的是: * 学习首选的字节结构。