精华内容
下载资源
问答
  • 常用缓冲技术有哪几种?

    千次阅读 2015-07-23 10:14:00
    缓冲、环形缓冲缓冲池 转载于:https://www.cnblogs.com/luo841997665/p/4669628.html

    双缓冲、环形缓冲、缓冲池

    转载于:https://www.cnblogs.com/luo841997665/p/4669628.html

    展开全文
  •  RCD Snubber是一种能耗式电压关断型缓冲器,分为抑制电压上升率模式和电压钳位模式两种类型,习惯上前者称为RCD Snubber电路,而后者则称为RCD Clamp电路。  为了分析方便,以下的分析或举例均针对反激电路拓扑...
  • 本文将介绍用于备受青睐的反激式转换器的最常用的RCD箝位电路,及其设计公式。  没有缓冲器,反激式变压器振铃的漏感会随电路中的杂散电容产生,生产大幅度高频波形,如图所示1。  许多应用笔记和设计没有解决...
  • 新型缓冲体在汽车音响产品包装中的设计与应用塑料薄膜包装的安全性票据印刷常用底纹防伪技术海外.pdf
  • 本文将介绍用于备受青睐的反激式转换器的最常用的RCD箝位电路,及其设计公式。  没有缓冲器,反激式变压器振铃的漏感会随电路中的杂散电容产生,生产大幅度高频波形,如图所示1。  许多应用笔记和设计没有解决这...
  • 摘要:液晶是嵌入式设备最常用的显示器件。本文详细介绍了用双缓冲的方式实现图形液晶的快速显示。  1. 引言  在嵌入式设备中,液晶已经成为显示器件的首选。液晶类型有字符和图形之分,字符液晶便宜且显示速度...
  • 本内容包括一些实验室基本溶液的配制,再进行分子试验时都会用到,分享给大家,一起学习
  • 摘要:在分析无源无损缓冲电路的拓扑分类和硬开关转换过程中开关损耗的基础... 有源缓冲电路、RCD缓冲电路、谐振变换器、无源无损缓冲电路是常用的软开关技术。其中,有源缓冲电路通过增添辅助开关以减少开关损耗,但
  • 以下是MSComm控件的常用属性和方法:  ●Commport:设置或返回串口号。  ●Settings:以字符串的形式设置或返回串口通信参数。  ●Portopen:设置或返回串口状态。  ●InputMode:设置或返回接收数据的类型...
  • java的双缓冲技术

    千次阅读 2016-03-19 23:54:17
    Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色。在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理。本文从J2SE的一个再现了屏幕闪烁的Java ...双缓冲是计算机动画处理中的传统技术,在

    Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色。在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理。本文从J2SE的一个再现了屏幕闪烁的Java Appilication简单动画实例展开,对屏幕闪烁的原因进行了分析,找出了闪烁成因的关键:update(Graphics g)函数对于前端屏幕的清屏。由此引出消除闪烁的方法——双缓冲。双缓冲是计算机动画处理中的传统技术,在用其他语言编程时也可以实现。本文从实例出发,着重介绍了用双缓冲消除闪烁的原理以及双缓冲在Java中的两种常用实现方法(即在update(Graphics g)中实现和在paint(Graphics g)中实现),以期读者能对双缓冲在Java编程中的应用能有个较全面的认识。

    一、问题的引入

    在编写Java多媒体动画程序或用Java编写游戏程序的时候,我们得到的动画往往存在严重的闪烁(或图片断裂)。这种闪烁虽然不会给程序的效果造成太大的影响,但着实有违我们的设计初衷,也给程序的使用者造成了些许不便。闪烁到底是什么样的呢?下面的JavaApplication再现了这种屏幕闪烁的情况:

    代码段一,闪烁再现

    [java]  view plain  copy
    1. import java.awt.*;  
    2. import java.awt.event.*;  
    3. public class DoubleBuffer extends Frame//主类继承Frame类  
    4. {  
    5.     public paintThread pT;//绘图线程  
    6.     public int ypos=-80//小圆左上角的纵坐标  
    7.     public DoubleBuffer()//构造函数  
    8.     {  
    9.        pT=new paintThread(this);  
    10.        this.setResizable(false);  
    11.        this.setSize(300,300); //设置窗口的首选大小  
    12.        this.setVisible(true); //显示窗口  
    13.        pT.start();//绘图线程启动  
    14.     }  
    15.    public void paint(Graphics scr) //重载绘图函数  
    16.    {  
    17.        scr.setColor(Color.RED);//设置小圆颜色  
    18.        scr.fillOval(90,ypos,80,80); //绘制小圆  
    19.     }  
    20.     public static void main(String[] args)  
    21.     {  
    22.        DoubleBuffer DB=new DoubleBuffer();//创建主类的对象  
    23.        DB.addWindowListener(new WindowAdapter()//添加窗口关闭处理函数  
    24.        {  
    25.            public void windowClosing(WindowEvent e)  
    26.            {  
    27.               System.exit(0);  
    28.            }});  
    29.     }  
    30. }  
    31. class paintThread extends Thread//绘图线程类  
    32. {  
    33.     DoubleBuffer DB;  
    34.        public paintThread(DoubleBuffer DB) //构造函数  
    35.        {  
    36.            this.DB=DB;  
    37.        }  
    38.        public void run()//重载run()函数  
    39.        {  
    40.            while(true)//线程中的无限循环  
    41.            {  
    42.               try{  
    43.                   sleep(30); //线程休眠30ms  
    44.                   }catch(InterruptedException e){}  
    45.               DB.ypos+=5//修改小圆左上角的纵坐标  
    46.               if(DB.ypos>300//小圆离开窗口后重设左上角的纵坐标  
    47.                   DB.ypos=-80;  
    48.               DB.repaint();//窗口重绘  
    49.            }  
    50.        }  
    51. }  

    编译、运行上述例子程序后,我们会看到窗体中有一个从上至下匀速运动的小圆,但仔细观察,你会发现小圆会不时地被白色的不规则横纹隔开,即所谓的屏幕闪烁,这不是我们预期的结果。


    这种闪烁是如何出现的呢?

    首先我们分析一下这段代码。DoubleBuffer的对象建立后,显示窗口,程序首先自动调用重载后的paint(Graphics g)函数,在窗口上绘制了一个小圆,绘图线程启动后,该线程每隔30ms修改一下小圆的位置,然后调用repaint()函数。

    注意,这个repaint()函数并不是我们重载的,而是从Frame类继承而来的。它先调用update(Graphics g)函数,update(Graphics g)再调用paint(Graphics g)函数。问题就出在update(Graphics g)函数,我们来看看这个函数的源代码:

    [java]  view plain  copy
    1. public void update(Graphics g)  
    2. {  
    3. if (isShowing())  
    4. {  
    5.         if (! (peer instanceof LightweightPeer))  
    6. {  
    7.              g.clearRect(00, width, height);  
    8.          }  
    9.         paint(g);  
    10.     }  
    11. }  

    以上代码的意思是:(如果该组件是轻量组件的话)先用背景色覆盖整个组件,然后再调用paint(Graphics g)函数,重新绘制小圆。这样,我们每次看到的都是一个在新的位置绘制的小圆,前面的小圆都被背景色覆盖掉了。这就像一帧一帧的画面匀速地切换,以此来实现动画的效果。

        但是,正是这种先用背景色覆盖组件再重绘图像的方式导致了闪烁。在两次看到不同位置小圆的中间时刻,总是存在一个在短时间内被绘制出来的空白画面(颜色取背景色)。但即使时间很短,如果重绘的面积较大的话花去的时间也是比较可观的,这个时间甚至可以大到足以让闪烁严重到让人无法忍受的地步。

        另外,用paint(Graphics g)函数在屏幕上直接绘图的时候,由于执行的语句比较多,程序不断地改变窗体中正在被绘制的图象,会造成绘制的缓慢,这也从一定程度上加剧了闪烁。

        就像以前课堂上老师用的旧式的幻灯机,放完一张胶片,老师会将它拿下去,这个时候屏幕上一片空白,直到放上第二张,中间时间间隔较长。当然,这不是在放动画,但上述闪烁的产生原因和这很类似。

    二、问题的解决

    知道了闪烁产生的原因,我们就有了更具针对性的解决闪烁的方案。已经知道update(Graphics g)是造成闪烁的主要原因,那么就从这里入手。

    1尝试这样重载update(Graphics g)函数(基于代码段一修改):


    [java]  view plain  copy
    1. public void update(Graphics scr)  
    2. {  
    3.     paint(scr);  
    4. }  

    以上代码在重绘小圆之前没有用背景色重绘整个画面,而是直接调用paint(Graphics g)函数,这就从根本上避免了上述的那幅空白画面。

        看看运行结果,闪烁果然消除了!但是更大的问题出现了,不同时刻绘制的小圆重叠在一起形成了一条线!这样的结果我们更不能接受了。为什么会这样呢?仔细分析一下,重载后的update(Graphics g)函数中没有了任何清屏的操作,每次重绘都是在先前已经绘制好的图象的基础上,当然会出现重叠的现象了。

    2)使用双缓冲:

    这是本文讨论的重点。所谓双缓冲,就是在内存中开辟一片区域,作为后台图象,程序对它进行更新、修改,绘制完成后再显示到屏幕上。  

    1、重载paint(Graphics g)实现双缓冲:

        这种方法要求我们将双缓冲的处理放在paint(Graphics g)函数中,那么具体该怎么实现呢?先看下面的代码(基于代码段一修改):

    DoubleBuffer类中添加如下两个私有成员:

    [java]  view plain  copy
    1. private Image iBuffer;  
    2. private Graphics gBuffer;  
    3. //重载paint(Graphics scr)函数:  
    4. public void paint(Graphics scr)  
    5. {  
    6.     if(iBuffer==null)  
    7.     {  
    8.        iBuffer=createImage(this.getSize().width,this.getSize().height);  
    9.        gBuffer=iBuffer.getGraphics();  
    10.     }  
    11.     gBuffer.setColor(getBackground());  
    12.     gBuffer.fillRect(0,0,this.getSize().width,this.getSize().height);  
    13.    gBuffer.setColor(Color.RED);  
    14.    gBuffer.fillOval(90,ypos,80,80);  
    15.     scr.drawImage(iBuffer,0,0,this);  
    16. }  

    分析上述代码:我们首先添加了两个成员变量iBuffergBuffer作为缓冲(这就是所谓的双缓冲名字的来历)。在paint(Graphics scr)函数中,首先检测如果iBuffernull,则创建一个和屏幕上的绘图区域大小一样的缓冲图象,再取得iBufferGraphics类型的对象的引用,并将其赋值给gBuffer,然后对gBuffer这个内存中的后台图象先用fillRect(int,int,int,int)清屏,再进行绘制操作,完成后将iBuffer直接绘制到屏幕上。

        这段代码看似可以完美地完成双缓冲,但是,运行之后我们看到的还是严重的闪烁!为什么呢?回想上文所讨论的,问题还是出现在update(Graphics g)函数!这段修改后的程序中的update(Graphics g)函数还是我们从父类继承的。在update(Graphics g)中,clearRect(int,int,int,int)对前端屏幕进行了清屏操作,而在paint(Graphics g)中,对后台图象又进行了清屏操作。那么如果保留后台清屏,去掉多余的前台清屏应该就会消除闪烁。所以,我们只要按照(1)中的方法重载update(Graphics g)即可:


    [java]  view plain  copy
    1. public void update(Graphics scr)  
    2. {  
    3.     paint(scr);  
    4. }  

    这样就避开了对前端图象的清屏操作,避免了屏幕的闪烁。虽然和(1)中用一样的方法重载update(Graphics g),但(1)中没有了清屏操作,消除闪烁的同时严重破坏了动画效果,这里我们把清屏操作放在了后台图象上,消除了闪烁的同时也获得了预期的动画效果。

    2、重载update(Graphics g)实现双缓冲:

        这是比较传统的做法。也是实际开发中比较常用的做法。我们看看实现这种方法的代码(基于代码段一修改):

    DoubleBuffer 类中添加如下两个私有成员:

    [java]  view plain  copy
    1. private Image iBuffer;  
    2. private Graphics gBuffer;  
    3. //重载paint(Graphics scr)函数:  
    4. public void paint(Graphics scr)  
    5. {  
    6.     scr.setColor(Color.RED);  
    7.     scr.fillOval(90,ypos,80,80);  
    8. }  

    重载update(Graphics scr)函数:


    [java]  view plain  copy
    1. public void update(Graphics scr)  
    2. {  
    3.     if(iBuffer==null)  
    4.     {  
    5.        iBuffer=createImage(this.getSize().width,this.getSize().height);  
    6.        gBuffer=iBuffer.getGraphics();  
    7.     }  
    8.        gBuffer.setColor(getBackground());  
    9.        gBuffer.fillRect(0,0,this.getSize().width,this.getSize().height);  
    10.        paint(gBuffer);  
    11.        scr.drawImage(iBuffer,0,0,this);  
    12. }  

    分析上述代码:我们把对后台图象的创建、清屏以及重绘等一系列动作都放在了update(Graphicsscr)函数中,而paint(Graphics g)函数只是负责绘制什么样的图象,以及怎样绘图,函数的最后实现了后台图象向前台绘制的过程。

    运行上述修改后的程序,我们会看到完美的消除闪烁后的动画效果。就像在电影院看电影,每张胶片都是在后台准备好的,播放完一张胶片之后,下一张很快就被播放到前台,自然不会出现闪烁的情形。

        为了让读者能对双缓冲有个全面的认识现将上述双缓冲的实现概括如下:

    1)定义一个Graphics对象gBuffer和一个Image对象iBuffer。按屏幕大小建立一个缓冲对象给iBuffer。然后取得iBufferGraphics赋给gBuffer。此处可以把gBuffer理解为逻辑上的缓冲屏幕,而把iBuffer理解为缓冲屏幕上的图象。

    2gBuffer(逻辑上的屏幕)上用paint(Graphics g)函数绘制图象。

    3将后台图象iBuffer绘制到前台。

    以上就是一次双缓冲的过程。注意,将这个过程联系起来的是repaint()函数。paint(Graphics g)是一个系统调用语句,不能由程序员手工调用。只能通过repaint()函数调用。

    三、问题的扩展

    1、关于闪烁的补充:

    其实引起闪烁的不仅仅是上文提到的那样,多种物理因素也可以引起闪烁,无论是CRT显示器还是LCD显示器都存在闪烁的现象。本文只讨论软件编程引起的闪烁。但是即使双缓冲做得再好,有时也是会有闪烁,这就是硬件方面的原因了,我们只能修改程序中的相关参数来降低闪烁(比如让画面动得慢一点),而不是编程方法的问题。

    2、关于消除闪烁的方法的补充:

        上文提到的双缓冲的实现方法只是消除闪烁的方法中的一种。如果在swing中,组件本身就提供了双缓冲的功能,我们只需要进行简单的函数调用就可以实现组件的双缓冲,在awt中却没有提供此功能。另外,一些硬件设备也可以实现双缓冲,每次都是先把图象画在缓冲中,然后再绘制在屏幕上,而不是直接绘制在屏幕上,基本原理还是和文中的类似的。还有其他用软件实现消除闪烁的方法,但双缓冲是个简单的、值得推荐的方法。

    2、关于双缓冲的补充:

    双缓冲技术是编写J2ME游戏的关键技术之一。双缓冲付出的代价是较大的额外内存消耗。但现在节省内存已经不再是程序员们考虑的最首要的问题了,游戏的画面在游戏制作中是至关重要的,所以以额外的内存消耗换取程序质量的提高还是值得肯定的。

    3、双缓冲的改进:

    有时动画中相邻的两幅画面只是有很少部分的不同,这就没必要每次都对整个绘图区进行清屏。我们可以对文中的程序进行修改,使之每次只对部分屏幕清屏,这样既能节省内存,又能减少绘制图象的时间,使动画更加连贯!
    展开全文
  • Java双缓冲技术详解

    千次阅读 2016-07-08 16:06:59
    Java双缓冲技术 返回 存档 删除 添加到收藏夹 分享 显示选项 Pocket 我的列表添加到收藏夹存档列表 文本视频图像标签 › Careers at PocketBecome a SponsorMore
    展开全文
  • Java双缓冲技术

    万次阅读 多人点赞 2012-10-28 10:38:52
    Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色。在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理。本文从J2SE的一个再现了屏幕闪烁的Java ...双缓冲是计算机动画处理中的传统技术,在

    Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色。在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理。本文从J2SE的一个再现了屏幕闪烁的Java Appilication简单动画实例展开,对屏幕闪烁的原因进行了分析,找出了闪烁成因的关键:update(Graphics g)函数对于前端屏幕的清屏。由此引出消除闪烁的方法——双缓冲。双缓冲是计算机动画处理中的传统技术,在用其他语言编程时也可以实现。本文从实例出发,着重介绍了用双缓冲消除闪烁的原理以及双缓冲在Java中的两种常用实现方法(即在update(Graphics g)中实现和在paint(Graphics g)中实现),以期读者能对双缓冲在Java编程中的应用能有个较全面的认识。

    一、问题的引入

    在编写Java多媒体动画程序或用Java编写游戏程序的时候,我们得到的动画往往存在严重的闪烁(或图片断裂)。这种闪烁虽然不会给程序的效果造成太大的影响,但着实有违我们的设计初衷,也给程序的使用者造成了些许不便。闪烁到底是什么样的呢?下面的JavaApplication再现了这种屏幕闪烁的情况:

    代码段一,闪烁再现

    import java.awt.*;
    import java.awt.event.*;
    public class DoubleBuffer extends Frame//主类继承Frame类
    {
        public paintThread pT;//绘图线程
        public int ypos=-80; //小圆左上角的纵坐标
        public DoubleBuffer()//构造函数
        {
           pT=new paintThread(this);
           this.setResizable(false);
           this.setSize(300,300); //设置窗口的首选大小
           this.setVisible(true); //显示窗口
           pT.start();//绘图线程启动
        }
       public void paint(Graphics scr) //重载绘图函数
       {
           scr.setColor(Color.RED);//设置小圆颜色
           scr.fillOval(90,ypos,80,80); //绘制小圆
        }
        public static void main(String[] args)
        {
           DoubleBuffer DB=new DoubleBuffer();//创建主类的对象
           DB.addWindowListener(new WindowAdapter()//添加窗口关闭处理函数
           {
               public void windowClosing(WindowEvent e)
               {
                  System.exit(0);
               }});
        }
    }
    class paintThread extends Thread//绘图线程类
    {
        DoubleBuffer DB;
           public paintThread(DoubleBuffer DB) //构造函数
           {
               this.DB=DB;
           }
           public void run()//重载run()函数
           {
               while(true)//线程中的无限循环
               {
                  try{
                      sleep(30); //线程休眠30ms
                      }catch(InterruptedException e){}
                  DB.ypos+=5; //修改小圆左上角的纵坐标
                  if(DB.ypos>300) //小圆离开窗口后重设左上角的纵坐标
                      DB.ypos=-80;
                  DB.repaint();//窗口重绘
               }
           }
    }
    

    编译、运行上述例子程序后,我们会看到窗体中有一个从上至下匀速运动的小圆,但仔细观察,你会发现小圆会不时地被白色的不规则横纹隔开,即所谓的屏幕闪烁,这不是我们预期的结果。


    这种闪烁是如何出现的呢?

    首先我们分析一下这段代码。DoubleBuffer的对象建立后,显示窗口,程序首先自动调用重载后的paint(Graphics g)函数,在窗口上绘制了一个小圆,绘图线程启动后,该线程每隔30ms修改一下小圆的位置,然后调用repaint()函数。

    注意,这个repaint()函数并不是我们重载的,而是从Frame类继承而来的。它先调用update(Graphics g)函数,update(Graphics g)再调用paint(Graphics g)函数。问题就出在update(Graphics g)函数,我们来看看这个函数的源代码:

    public void update(Graphics g)
    {
    if (isShowing())
    {
            if (! (peer instanceof LightweightPeer))
    {
                 g.clearRect(0, 0, width, height);
             }
            paint(g);
        }
    }
    

    以上代码的意思是:(如果该组件是轻量组件的话)先用背景色覆盖整个组件,然后再调用paint(Graphics g)函数,重新绘制小圆。这样,我们每次看到的都是一个在新的位置绘制的小圆,前面的小圆都被背景色覆盖掉了。这就像一帧一帧的画面匀速地切换,以此来实现动画的效果。

        但是,正是这种先用背景色覆盖组件再重绘图像的方式导致了闪烁。在两次看到不同位置小圆的中间时刻,总是存在一个在短时间内被绘制出来的空白画面(颜色取背景色)。但即使时间很短,如果重绘的面积较大的话花去的时间也是比较可观的,这个时间甚至可以大到足以让闪烁严重到让人无法忍受的地步。

        另外,用paint(Graphics g)函数在屏幕上直接绘图的时候,由于执行的语句比较多,程序不断地改变窗体中正在被绘制的图象,会造成绘制的缓慢,这也从一定程度上加剧了闪烁。

        就像以前课堂上老师用的旧式的幻灯机,放完一张胶片,老师会将它拿下去,这个时候屏幕上一片空白,直到放上第二张,中间时间间隔较长。当然,这不是在放动画,但上述闪烁的产生原因和这很类似。

    二、问题的解决

    知道了闪烁产生的原因,我们就有了更具针对性的解决闪烁的方案。已经知道update(Graphics g)是造成闪烁的主要原因,那么就从这里入手。

    1尝试这样重载update(Graphics g)函数(基于代码段一修改):


    public void update(Graphics scr)
    {
        paint(scr);
    }
    

    以上代码在重绘小圆之前没有用背景色重绘整个画面,而是直接调用paint(Graphics g)函数,这就从根本上避免了上述的那幅空白画面。

        看看运行结果,闪烁果然消除了!但是更大的问题出现了,不同时刻绘制的小圆重叠在一起形成了一条线!这样的结果我们更不能接受了。为什么会这样呢?仔细分析一下,重载后的update(Graphics g)函数中没有了任何清屏的操作,每次重绘都是在先前已经绘制好的图象的基础上,当然会出现重叠的现象了。

    2)使用双缓冲:

    这是本文讨论的重点。所谓双缓冲,就是在内存中开辟一片区域,作为后台图象,程序对它进行更新、修改,绘制完成后再显示到屏幕上。  

    1、重载paint(Graphics g)实现双缓冲:

        这种方法要求我们将双缓冲的处理放在paint(Graphics g)函数中,那么具体该怎么实现呢?先看下面的代码(基于代码段一修改):

    DoubleBuffer类中添加如下两个私有成员:

    private Image iBuffer;
    private Graphics gBuffer;
    //重载paint(Graphics scr)函数:
    public void paint(Graphics scr)
    {
        if(iBuffer==null)
        {
           iBuffer=createImage(this.getSize().width,this.getSize().height);
           gBuffer=iBuffer.getGraphics();
        }
        gBuffer.setColor(getBackground());
        gBuffer.fillRect(0,0,this.getSize().width,this.getSize().height);
       gBuffer.setColor(Color.RED);
       gBuffer.fillOval(90,ypos,80,80);
        scr.drawImage(iBuffer,0,0,this);
    }
    

    分析上述代码:我们首先添加了两个成员变量iBuffergBuffer作为缓冲(这就是所谓的双缓冲名字的来历)。在paint(Graphics scr)函数中,首先检测如果iBuffernull,则创建一个和屏幕上的绘图区域大小一样的缓冲图象,再取得iBufferGraphics类型的对象的引用,并将其赋值给gBuffer,然后对gBuffer这个内存中的后台图象先用fillRect(int,int,int,int)清屏,再进行绘制操作,完成后将iBuffer直接绘制到屏幕上。

        这段代码看似可以完美地完成双缓冲,但是,运行之后我们看到的还是严重的闪烁!为什么呢?回想上文所讨论的,问题还是出现在update(Graphics g)函数!这段修改后的程序中的update(Graphics g)函数还是我们从父类继承的。在update(Graphics g)中,clearRect(int,int,int,int)对前端屏幕进行了清屏操作,而在paint(Graphics g)中,对后台图象又进行了清屏操作。那么如果保留后台清屏,去掉多余的前台清屏应该就会消除闪烁。所以,我们只要按照(1)中的方法重载update(Graphics g)即可:


    public void update(Graphics scr)
    {
        paint(scr);
    }
    

    这样就避开了对前端图象的清屏操作,避免了屏幕的闪烁。虽然和(1)中用一样的方法重载update(Graphics g),但(1)中没有了清屏操作,消除闪烁的同时严重破坏了动画效果,这里我们把清屏操作放在了后台图象上,消除了闪烁的同时也获得了预期的动画效果。

    2、重载update(Graphics g)实现双缓冲:

        这是比较传统的做法。也是实际开发中比较常用的做法。我们看看实现这种方法的代码(基于代码段一修改):

    DoubleBuffer 类中添加如下两个私有成员:

    private Image iBuffer;
    private Graphics gBuffer;
    //重载paint(Graphics scr)函数:
    public void paint(Graphics scr)
    {
        scr.setColor(Color.RED);
        scr.fillOval(90,ypos,80,80);
    }
    

    重载update(Graphics scr)函数:


    public void update(Graphics scr)
    {
        if(iBuffer==null)
        {
           iBuffer=createImage(this.getSize().width,this.getSize().height);
           gBuffer=iBuffer.getGraphics();
        }
           gBuffer.setColor(getBackground());
           gBuffer.fillRect(0,0,this.getSize().width,this.getSize().height);
           paint(gBuffer);
           scr.drawImage(iBuffer,0,0,this);
    }
    

    分析上述代码:我们把对后台图象的创建、清屏以及重绘等一系列动作都放在了update(Graphicsscr)函数中,而paint(Graphics g)函数只是负责绘制什么样的图象,以及怎样绘图,函数的最后实现了后台图象向前台绘制的过程。

    运行上述修改后的程序,我们会看到完美的消除闪烁后的动画效果。就像在电影院看电影,每张胶片都是在后台准备好的,播放完一张胶片之后,下一张很快就被播放到前台,自然不会出现闪烁的情形。

        为了让读者能对双缓冲有个全面的认识现将上述双缓冲的实现概括如下:

    1)定义一个Graphics对象gBuffer和一个Image对象iBuffer。按屏幕大小建立一个缓冲对象给iBuffer。然后取得iBufferGraphics赋给gBuffer。此处可以把gBuffer理解为逻辑上的缓冲屏幕,而把iBuffer理解为缓冲屏幕上的图象。

    2gBuffer(逻辑上的屏幕)上用paint(Graphics g)函数绘制图象。

    3将后台图象iBuffer绘制到前台。

    以上就是一次双缓冲的过程。注意,将这个过程联系起来的是repaint()函数。paint(Graphics g)是一个系统调用语句,不能由程序员手工调用。只能通过repaint()函数调用。

    三、问题的扩展

    1、关于闪烁的补充:

    其实引起闪烁的不仅仅是上文提到的那样,多种物理因素也可以引起闪烁,无论是CRT显示器还是LCD显示器都存在闪烁的现象。本文只讨论软件编程引起的闪烁。但是即使双缓冲做得再好,有时也是会有闪烁,这就是硬件方面的原因了,我们只能修改程序中的相关参数来降低闪烁(比如让画面动得慢一点),而不是编程方法的问题。

    2、关于消除闪烁的方法的补充:

        上文提到的双缓冲的实现方法只是消除闪烁的方法中的一种。如果在swing中,组件本身就提供了双缓冲的功能,我们只需要进行简单的函数调用就可以实现组件的双缓冲,在awt中却没有提供此功能。另外,一些硬件设备也可以实现双缓冲,每次都是先把图象画在缓冲中,然后再绘制在屏幕上,而不是直接绘制在屏幕上,基本原理还是和文中的类似的。还有其他用软件实现消除闪烁的方法,但双缓冲是个简单的、值得推荐的方法。

    2、关于双缓冲的补充:

    双缓冲技术是编写J2ME游戏的关键技术之一。双缓冲付出的代价是较大的额外内存消耗。但现在节省内存已经不再是程序员们考虑的最首要的问题了,游戏的画面在游戏制作中是至关重要的,所以以额外的内存消耗换取程序质量的提高还是值得肯定的。

    3、双缓冲的改进:

    有时动画中相邻的两幅画面只是有很少部分的不同,这就没必要每次都对整个绘图区进行清屏。我们可以对文中的程序进行修改,使之每次只对部分屏幕清屏,这样既能节省内存,又能减少绘制图象的时间,使动画更加连贯!




    展开全文
  • 文章尝试用尝试用通俗的语言还原密码学应用逻辑与信息传输加密方法,梳理常用加密技术原理及学科学习中的关键要点。
  • QT_双缓冲技术1

    千次阅读 2013-03-05 13:51:55
    Rubber band(橡皮筋线,或者橡皮线), pixmap(图像,双缓冲中用到的图像,有时也直呼pixmap),off-screen pixmap(离线图像) ...双缓冲技术是GUI编程中常用的技术。所谓的双缓冲就是把把一个需要渲染的
  • 引入缓冲技术的原因: 1、 为了进一步缓和CPU和I/O设备之间速度不匹配的矛盾。 2、 提高CPU与I/O设备之间的并行性。 3、 为了减少中断次数和CPU的中断处理时间。如果没有缓冲,慢速I/O设备每传一个字节就要产生一...
  • 三态缓冲器可以处于以下三种状态之一:逻辑0,逻辑1和Z(高阻抗)。它们的使用允许多个驱动程序共享一条公共线路。这使得它们在半双工通信中特别有用。让我们首先讨论半双工和全双工通信之间的区别。
  • Java 中的缓冲

    千次阅读 2019-05-17 12:12:16
    在读写数据时,让数据在缓冲区能够减少系统实际对原始数据来源的存取次数,因为一次能做多个数据单位的操作。相较而言,对于直接从文件读取数据或将数据写入文件,比起缓冲区的读写要慢多了。所以使用缓冲区的流,...
  • Linux文件系统中,存在着著名的三大缓冲技术用以提升读写操作效率:inode缓冲区、dentry缓冲区、块缓冲。其中所谓的块缓冲便是我们前面一直在讨论的缓冲池技术,常用来配备IO操作,用来减少IO读取次数,以提升系统...
  • java缓冲

    万次阅读 2018-11-26 21:38:43
    1 缓冲区的分类 ByteBuffer CharBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer 2 ByteBuffer读取数据的操作 容量(capacity):表示Buffer最大数据容量,缓冲区容量不能为负,并且建立后不能...
  • 缓存的基本概念和常用的缓存技术

    万次阅读 多人点赞 2018-04-04 11:15:22
    摘要: 介绍缓存的基本概念和常用的缓存技术,给出了各种技术的实现机制的简单介绍和适用范围说明,以及设计缓存方案应该考虑的问题(共17页)1 概念1.1 缓存能解决的问题· 性能——将相应数据存储起来以避免数据...
  • 缓冲技术 在互联网服务中,大部分的用户交互,都是需要立刻返回结果的,所以对于延迟有一定的要求。而类似网络游戏之类服务,延迟更是要求缩短到几十毫秒以内。所以为了降低延迟,缓冲是互联网服务中最常见的技术...
  • 【Java基础-3】吃透Java IO:字节流、字符流、缓冲

    万次阅读 多人点赞 2020-09-23 20:12:33
    什么是Java-IO?字符流和字节流的区别与适用场景是什么?缓冲流到底实现了什么?如何高效地读写文件? 本文用大量的示例图和实例,带你吃透Java IO。
  • 本文从检测程序的漏洞方面着手,比较了以前常用的静态代码分析和实时错误注入的检测方法,提出了一种对可执行文件反汇编后的代码进行缓冲区溢出漏洞检测的技术, 提高了检测软件系统漏洞的效率。
  • 谐振 1 引言 双管串联单正激电路在高频大功率变换器中是一种常用的主功率电路,该电路的优点是主功率管耐压低,成本低。缺点是主变(高频变压器)磁芯的磁化方向为单向的,比起桥式电路差一半。该电路一般应用在...
  • 什么是缓冲区溢出?有说明危害?

    千次阅读 2019-04-19 20:40:04
     缓存溢出(或译为缓冲溢出)为黑客最为常用的攻击手段之-一,蠕虫病毒对操作系统高危漏洞的溢出高速与大规模传播均是利用此技术。  缓存溢出攻击从理论上来讲可以用于攻击任何有缺陷不完美的程序,包括对杀毒软件...
  • 缓冲技术、位图透明处理、位图半透明处理、物理运动、匀速运动……
  • 网络常用入侵技术分析

    千次阅读 2017-05-14 15:47:59
    9、偷取聊天记录特权 利用各种特洛伊木马程序、后门程序和黑客自己编写的导致缓冲区溢出的程序进行攻击,前者可使黑客非法获得对用户机器的完全控制权,后者可使黑客获得超级用户的权限,从而拥有对整个网络的绝对...
  • 缓冲(buffer)和缓存(cache)区别

    千次阅读 多人点赞 2018-12-08 21:20:54
    缓存(cache)是在读取硬盘中的数据时,把最常用的数据保存在内存的缓存区中,再次读取该数据时,就不去硬盘中读取了,而在缓存中读取。 缓冲(buffer)是在向硬盘写入数据时,先把数据放入缓冲区,然后再一起向硬盘...
  • 缓冲(caching)技术在网络应用程序中的作用非常...问题显得更加严重,于是就有了缓冲技术的出现,它将动态生成的静态网页保存起来,当客户端有相同的请求时就直接将已保存的网页发送过去,大大的提高了浏览速度和工
  • java IO流 [缓冲技术] [装饰设计模式]

    千次阅读 2013-01-06 20:48:38
    IO流流的分类字符流的由来乱码的出现读写流流的读写操作WriterReader缓冲技术IO异常装饰设计模式InputStreamReader IO流  IO流---input 和 output 的简写,用来处理设备之间的数据传输 如内存 硬盘 网络等

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,769
精华内容 45,107
关键字:

常用的缓冲技术是