因为系统涉及到比较多的图形处理,而且重绘比较频繁,所以想在图形方面做些比较深入的工作。关于双缓存,以前也早有听说,只是一直没怎么用,因为总听说JavaGui很多组建已经在内部实现了双缓存。当然GUi内部是否实现了双缓冲,我没有仔细研究,只是我在自己的系统中绘图时发现,自己没实现双缓冲,画面并不闪烁,只是稍微有点慢。基于这种原因,前几天我将所有图像采用了缓冲技术,绘制背景的具体代码如下:
BufferedImage offImg;
if (offImg == null
|| offImg.getWidth() != d.width
|| offImg.getHeight() != d.height){
offImg = null;
offImg = new BufferedImage(
d.width, d.height, BufferedImage.TYPE_INT_RGB);
Graphics g2 = offImg.getGraphics();
g2.setColor(bgColor);
g2.fillRect(0,0,d.width,d.height); drawBack(g2);
if (drawGrid)
drawBackGrid(g2);
} Graphics g = this.getGraphics();
g.drawImage(offImg,0,0,d.width,d.height,null); 这样的话,每次图片重绘时,只是将BufferedImage复制到目标面板,经过测试,速度确实快了一点,但是面板重绘一次至少要增加2M内容,刷新10多次,内存就溢出了。如果不用BufferedImage,而是直接在组件上绘图,就没有内存溢出的问题,仔细查看程序,发现唯一可能浪费内存的地方只有图形复制方法g.drawImage(offImg,0,0,d.width,d.height,null);
不知道大家有没有真的用过BufferedImage,如果用过是否也遇上了内存溢出的问题,应该如何解决呢?
BufferedImage offImg;
if (offImg == null
|| offImg.getWidth() != d.width
|| offImg.getHeight() != d.height){
offImg = null;
offImg = new BufferedImage(
d.width, d.height, BufferedImage.TYPE_INT_RGB);
Graphics g2 = offImg.getGraphics();
g2.setColor(bgColor);
g2.fillRect(0,0,d.width,d.height); drawBack(g2);
if (drawGrid)
drawBackGrid(g2);
} Graphics g = this.getGraphics();
g.drawImage(offImg,0,0,d.width,d.height,null); 这样的话,每次图片重绘时,只是将BufferedImage复制到目标面板,经过测试,速度确实快了一点,但是面板重绘一次至少要增加2M内容,刷新10多次,内存就溢出了。如果不用BufferedImage,而是直接在组件上绘图,就没有内存溢出的问题,仔细查看程序,发现唯一可能浪费内存的地方只有图形复制方法g.drawImage(offImg,0,0,d.width,d.height,null);
不知道大家有没有真的用过BufferedImage,如果用过是否也遇上了内存溢出的问题,应该如何解决呢?
|| offImg.getWidth() != d.width
|| offImg.getHeight() != d.height){
offImg = null;
offImg = new BufferedImage(
d.width, d.height, BufferedImage.TYPE_INT_RGB);
Graphics g2 = offImg.getGraphics();
g2.setColor(bgColor);
g2.fillRect(0,0,d.width,d.height); drawBack(g2);
if (drawGrid)
drawBackGrid(g2);
g2.dispose(); // 加上这句.
}
上面的代码只有改变窗口的大小时, 才会创建新的BufferedImage, 刷新怎么会增加内存? 这点不明白.Graphics g = this.getGraphics(); // 不知为什么要这样用, 而不是直接使用paint或者paintComponent提供的Graphics g.
g.drawImage(offImg,0,0,d.width,d.height,null);
Graphics g = this.getGraphics();
和
paint(Graphics g);
有什么区别么?
一个是直接获取当前控件所属Graphics对象
一个是重绘过程中调用的方法。。
难道有相同点嘛?我能明白lz的意思,不过问题有点那个了- -
使用getGraphics(),在非重绘代码中进行描绘,你会面临一个很严重的问题:界面隐藏再显示后,你所描绘的内容会完全消失。
所以,慎用getGraphics()获取的对象进行描绘,你不知道什么时候你的操作就成了无用功。paint(Graphics g)方法是重量控件的重绘过程中调用的方法。在此的代码每次重绘过程中都会被调用到。
对应的,轻量控件中有paintComponent方法。
欢迎一起讨论,难道所谓的双缓存全都是骗人的?
首先你现在面对的是内存问题,而不是双缓冲,双缓冲改善的不是内存,而是闪烁。请检查你的代码。
BufferedImage毫无问题,我们软件界面刷新一次需要更新几十个BufferedImage,也没出现所谓的内存溢出。
对于一个比较稳健的API,你所应该做的不是去怀疑,而是去尝试
至少g.drawImage不是用来复制图片的。。
事实上不用BufferedImage也没出现闪烁,
当然如果不用BufferedImage图形绘制稍微有点慢,
但是在操作过程中用户没有明显的感觉,因为只是10毫秒与100毫秒的差别。
如果你认为没有内存溢出,那只能说你没遇到这样的问题,
我一般在问问题前都先去网上查阅大量的资料,所以不用怀疑我在瞎问。
最后对于你的
=======================
对于一个比较稳健的API,你所应该做的不是去怀疑,而是去尝试
=======================
实在不敢苟同,对于天天客户要使用的实际应用系统,
如果开发商没有经过所有细节的严格测试,是极其不负责任的。
如果现在我将图形采用这类双缓冲,可能客户天天会找我的麻烦,
这就是我遇到的问题。