如何在JPanel上快速有效地加载图片

mr桀骜不驯 发布于 2012/09/20 11:25
阅读 3K+
收藏 0

不知道大家在用Java写UI界面的时候有没有遇到过想这样的问题:在一个面板(JPanel)上添加图片就像这样:

    centerPanel = new JPanel() {
            @Override
            public void paint(Graphics g) {
                AImage img = (AImage) image[index];
                g.drawImage(img.getImage(), (this.getWidth() - img.getOriginalWidth(this)) / 2,
                        (this.getHeight() - img.getOriginalHeight(this)) / 2, this);
            }
        };

当你在调用repaint()让面板上显示另一张图片的时候,第二张照片就直接draw在第一张的上面,就像这样(第一张图片的尺寸比第二张的大):

而且当你在面板上切换很多张图片的时候,你之前加载过的图片会一直驻留在内存里面,当图片达到一定数量的时候内存就溢出了。

后来试过在JLabel上通过setIcon(Icon icon)方法添加图片,但是这样加载的速度会慢很多,而且同样会由于加载图片过多而造成内存溢出。

总的来说我的问题就是:如何在面板上快速加载图片,而且当频繁切换图片时不会造成太多内存开销,求各位大侠帮忙!!!

加载中
0
Jeky
Jeky

直接在Swing中读取大文件会导致前台卡死,如果图片不消失,那应该是你的程序写的问题

基本上逻辑是:

用一个成员变量保存当前的image
当点击上一张或者下一张的时候更新这个image,并repaint显示界面
显示的JPanel里就是绘制这个image

或着你要是方便上代码就上个代码

mr桀骜不驯
mr桀骜不驯
似乎不止是按钮,窗口里的所有组件都会向右边移位
mr桀骜不驯
mr桀骜不驯
嗯,这样做可以了,先谢谢你,那我想再问一下就是当某个对象失去了他的引用之后,比如Image img1=new Image(...); img1=new Image(...) ; 那么原来img1指向的Image对象就会从内存消失吗? 然后还有就是当我调用repaint()对整个窗口重绘的时候,会有一些组件被多画了一次,比如就是重绘之后同一个按钮出现两次,这会是什么原因呢?
0
Jeky
Jeky
图片有多少 一共有多大?
mr桀骜不驯
mr桀骜不驯
回复 @JekyCui : 因为显示的尺寸是按照屏幕大小缩放的,所以感觉这样效果也不会很好吧
Jeky
Jeky
回复 @mr桀骜不驯 : 压缩一下 降低一下尺寸 降低一下质量
mr桀骜不驯
mr桀骜不驯
回复 @JekyCui : 如果一次加载到内存的话,内存就会爆啦
Jeky
Jeky
回复 @mr桀骜不驯 : 建议压缩 然后一次性全部读取至内存 这样切换最流畅
mr桀骜不驯
mr桀骜不驯
图片1M到几M/张 总共可达到500~600M
0
Jeky
Jeky
你还是说说详细需求吧 这样优化没啥意义 比如说你是要个幻灯片或者屏保?
mr桀骜不驯
mr桀骜不驯
其实我在做的是一个类似于美图看看的图片浏览器 现在的问题就是 双击某个图片全屏查看大图,然后点击上一张或者下一张切换图片
0
Jeky
Jeky

点击上一张或者下一张的时候直接读取图片,读取的时候采用后台线程加载,前台弄个加载中之类的图标,加载完成后显示。

进一步改进的办法是缓存上一张,预读后一张,这样基本能保证效果

mr桀骜不驯
mr桀骜不驯
其实现在图片切换时加载的速度还是可以接受的,只是加载的图片会重叠在一起,而且加载过的图片一直驻留在内存并不会因为图片的切换而注销掉 另外还想请问一下为什么用后台线程啊?
0
Jeky
Jeky

第一个问题,如果没有其他引用,那么会被gc(但不一定是瞬间就会被gc掉)

第二个问题,应该是代码问题。Swing组件重绘,应该覆盖该组件的paintComponent方法,并在paintComponent方法的第一行调用super.paintComponent()。看看是不是这个问题

mr桀骜不驯
mr桀骜不驯
嗯,对就是这样,搞定了,学到东西了,谢谢你
0
MOsky
MOsky
在paint(G g)方法前面加一行:super.paint(g);即可解决。 至于载入,用后台线程预判吧。就是预计到下一张图片是什么,然后后台载入。
0
MOsky
MOsky
paint方法只不过是在graphics上重复绘制图片。graphics的面积只有那么大,占用的内存是固定的。不要因为视觉上看见图片叠加上去了,就以为存了N张图片。不是的,graphics就算是一片黑,或者看起来叠加了N张图片,占用内存是一样的。
许Mr
许Mr
回复 @mr桀骜不驯 : 他说的应该是显存
mr桀骜不驯
mr桀骜不驯
但是我不停的切换图片的时候,资源管理器上显示的所用内存是不停地跟着增加的啵
返回顶部
顶部