2008年3月26日 星期三

[Java] 為什麼元件重畫時會閃爍

你的元件 paint() 被呼叫時, 在 Swing 的設計下,
預設的呼叫順序情況如下.

Step 1: paintComponent(Graphics g): 畫出目前元件的樣子
Step 2: paintBorder(Graphics g): 畫出目前的外框
Step 3: paintChildren(Graphics g): 呼叫所包含元件的 paint()

所以如果你的元件, 直接 override paint method,
然後不寫任何程式碼.

public void paint(Graphics g){

}

那麼你的元件+外框+所有的子元件都不會被畫出來.

  

為何畫元件時, 會產生閃爍的現象? -- 簡單的說, 就是因為你的 paintComponent 呼叫了清除畫面的程式碼.

 

JDK 中 paintComponent method 實作長相大致上如下:

protected void paintComponent(Graphics g) {
        if (ui != null) {
       
// 如果有安裝 UI Delegate, 則呼叫 ui 的 update method
            Graphics scratchGraphics = (g == null) ? null : g.create();
            try {
                ui.update(scratchGraphics, this);
            }
            finally {
                scratchGraphics.dispose();
            }
        }
    }

其中 ui 的 update method 實作, 如下:

public void update(Graphics g, JComponent c) {
if (c.isOpaque()) {
   //  不透明
//  
下面這段就是為什麼, 元件重畫時會閃爍的原因
     g.setColor(c.getBackground());
     g.fillRect(0, 0, c.getWidth(),c.getHeight());
}
paint(g, c);  // <----- 這邊才是畫出預設元件的畫面
}

所以預設的情況下, 就是會閃爍. 為了防止這種情況, 你應該自己寫一個 paintComponent 繞過清背景的程式碼.

這樣你的元件就不會閃爍了.

References

1. http://java.sun.com/products/jfc/tsc/articles/painting/#paint_process

2. http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JComponent.html

3. http://www.javafaq.nu/java-allbooks-8.html

 

沒有留言:

張貼留言