因为系统涉及到比较多的图形处理,而且重绘比较频繁,所以想在图形方面做些比较深入的工作。关于双缓存,以前也早有听说,只是一直没怎么用,因为总听说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,如果用过是否也遇上了内存溢出的问题,应该如何解决呢?

解决方案 »

  1.   

    你用完了,dispose()销毁不就好了?
      

  2.   

     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);
                g2.dispose(); // 加上这句.
            }
    上面的代码只有改变窗口的大小时, 才会创建新的BufferedImage, 刷新怎么会增加内存? 这点不明白.Graphics g = this.getGraphics(); // 不知为什么要这样用, 而不是直接使用paint或者paintComponent提供的Graphics g.
            g.drawImage(offImg,0,0,d.width,d.height,null);
      

  3.   

    晕,这些代码只是简单的示意,
    Graphics g = this.getGraphics(); 

    paint(Graphics g);
    有什么区别么?
      

  4.   


    一个是直接获取当前控件所属Graphics对象
    一个是重绘过程中调用的方法。。
    难道有相同点嘛?我能明白lz的意思,不过问题有点那个了- -
    使用getGraphics(),在非重绘代码中进行描绘,你会面临一个很严重的问题:界面隐藏再显示后,你所描绘的内容会完全消失。
    所以,慎用getGraphics()获取的对象进行描绘,你不知道什么时候你的操作就成了无用功。paint(Graphics g)方法是重量控件的重绘过程中调用的方法。在此的代码每次重绘过程中都会被调用到。
    对应的,轻量控件中有paintComponent方法。
      

  5.   

    有没有真的在应用系统中大量使用过BufferedImage的人?
    欢迎一起讨论,难道所谓的双缓存全都是骗人的?
      

  6.   

    BufferedImage 没有问题,我们的图形界面一次翻页几十个BufferedImage一起更新另外,双缓冲和内存溢出没有一点关系
      

  7.   

    BufferedImage 没有问题,我们的图形界面一次翻页几十个BufferedImage一起更新另外,双缓冲和内存溢出没有一点关系
      

  8.   

    BufferedImage 没有问题,我们的图形界面一次翻页几十个BufferedImage一起更新,你更应该检查一下自己程序中是否存在内存问题而不是怀疑BufferedImage另外,双缓冲和内存溢出没有一点关系
      

  9.   

    你理解的方向有问题
    首先你现在面对的是内存问题,而不是双缓冲,双缓冲改善的不是内存,而是闪烁。请检查你的代码。
    BufferedImage毫无问题,我们软件界面刷新一次需要更新几十个BufferedImage,也没出现所谓的内存溢出。
    对于一个比较稳健的API,你所应该做的不是去怀疑,而是去尝试
      

  10.   

    最后,你的几个方法理解上有问题
    至少g.drawImage不是用来复制图片的。。
      

  11.   

    如果g.drawImage不是复制图片,那Java只能被说成弱智。
    事实上不用BufferedImage也没出现闪烁,
    当然如果不用BufferedImage图形绘制稍微有点慢,
    但是在操作过程中用户没有明显的感觉,因为只是10毫秒与100毫秒的差别。
    如果你认为没有内存溢出,那只能说你没遇到这样的问题,
    我一般在问问题前都先去网上查阅大量的资料,所以不用怀疑我在瞎问。
    最后对于你的
    =======================
    对于一个比较稳健的API,你所应该做的不是去怀疑,而是去尝试
    =======================
    实在不敢苟同,对于天天客户要使用的实际应用系统,
    如果开发商没有经过所有细节的严格测试,是极其不负责任的。
    如果现在我将图形采用这类双缓冲,可能客户天天会找我的麻烦,
    这就是我遇到的问题。