2015-05-20 76 views
1

我正在嘗試使用AWT在方法paint()中雙緩衝包含多邊形的圖像。使用Image對象進行緩衝處理,我將圖像背景設置爲黑色,將多邊形繪製到圖像上,然後將緩衝圖像繪製到屏幕上。然後我打電話給repaint()以便再次渲染圖像。連續雙緩衝解決方案不起作用

不幸的是,我仍然在重新繪製圖像時接收到僞像。我做錯了什麼?

編輯:作爲一個方面說明,我使用Java 8 編輯2:我在paint()打電話repaint(),因爲我需要不斷緩衝區中的圖像。該多邊形是爲了在用戶輸入的基礎上翻譯屏幕。

import java.applet.Applet; 
import java.awt.*; 

public class DoubleBuffer extends Applet { 
    int xSize = 900; 
    int ySize = 600; 

    Image bufferImage; 
    Graphics bufferG; 

    @Override 
    public void init() { 
     this.setSize(xSize, ySize); 

     //Double buffering related variables 
     bufferImage = this.createImage(xSize, xSize); 
     bufferG = bufferImage.getGraphics(); 
    } 

    //BUFFERING DONE HERE 
    @Override 
    public void paint(Graphics g){ 
     //drawing images to external image first (buffering) 
     bufferG.setColor(Color.BLACK); 
     bufferG.fillRect(0,0,xSize,ySize); 
     bufferG.setColor(Color.WHITE); 
     bufferG.drawRect(100, 100, 100, 100); 

     //draw the image and call repaint 
     g.drawImage(bufferImage, 0, 0, this); 
     repaint(); 
    } 
} 
+1

任何理由*不*使用輕量級組件(比如JPanel中),這是默認雙緩衝? (我會推薦* not *在'paint'方法中調用'repaint') – copeg

+0

聽起來很奇怪,因爲某些API約束我使用重量級組件(即只是窗口)工作(請與我聯繫)。如果一切都失敗了,我會繼續並使用一個輕量級組件。我即將展開更多研究,但在paint()中使用repaint()會出現什麼問題?我應該在哪裏重新呈現我的形象? –

+0

P.S.這是一個教育相關的工作,其中圖像渲染形成了一小部分 - 我幾乎沒有在這方面的經驗。 –

回答

2

的問題是,你是不是覆蓋update這是將響應repaint請求調用的方法。對於重量較輕的組件,update的默認實現將首先將組件清除爲背景顏色(可能默認爲白色),然後調用您的paint方法。

正如其他人所指出的,您不應該在paint方法中調用repaint。您應該使用Timer

清理後,整個班級的樣子:

public class DoubleBuffer extends Applet { 
    int xSize = 900; 
    int ySize = 600; 

    Image bufferImage; 
    Graphics bufferG; 
    Timer timer=new Timer(200, ev->repaint()); 

    @Override 
    public void init() { 
     this.setSize(xSize, ySize); 
    } 

    @Override 
    public void addNotify() { 
     super.addNotify(); 
     //Double buffering related variables 
     bufferImage = this.createImage(xSize, xSize); 
     bufferG = bufferImage.getGraphics(); 
     timer.start(); 
    } 

    @Override 
    public void removeNotify() { 
     super.removeNotify(); 
     bufferImage = null; 
     bufferG = null; 
     timer.stop(); 
    } 


    //BUFFERING DONE HERE 
    @Override 
    public void paint(Graphics g){ 
     //drawing images to external image first (buffering) 
     bufferG.setColor(Color.BLACK); 
     bufferG.fillRect(0,0,xSize,ySize); 
     bufferG.setColor(Color.WHITE); 
     bufferG.drawRect(100, 100, 100, 100); 

     //draw the image and call repaint 
     g.drawImage(bufferImage, 0, 0, this); 
    } 

    @Override 
    public void update(Graphics g) { 
     // now not clearing the background as we expect paint() to fill the entire area 
     this.paint(g); 
    } 
} 
+0

值得注意的是,簡單地通過'actionPerformed()'調用repaint()'(由Timer觸發)作爲我自己的解決方案,正如我在問題的評論中所述。無論如何,我還會重寫'update()',因爲其他(離線)源會支持您的聲明。 –

+1

@ c4goldsw:這可能是一個系統相關的副作用。由於時間不可預知,重複的填充操作可能會發生得太快,以至於您不會注意到它。在我的機器上,使用「Timer」大大減少了閃爍,但並未完全消除。所以我們需要重寫'update',我想可能會有系統/ Java版本在不重寫'update'的情況下可能會產生更大的影響。 – Holger

+0

我錯了 - 當我第一次報道copeg的解決方案正在工作時,我的計時器以非常低的速度執行(每秒一次)。增加計時器「滴答」造成工件的速率,因此實際上有必要重寫和修改update()。 –

相關問題