2012-06-03 146 views
3

我想出了我的previous question解決方案,使我陷入了新的問題。重繪圖像閃爍()

在下面的代碼中,即時通過使用箭頭鍵移動一個圖像周圍的JFrame。但每當我按下箭頭鍵時,圖像似乎都會閃爍,這在連續按下按鍵時非常明顯。

import java.awt.Graphics; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 


public class TestProgram extends JFrame implements KeyListener { 
    private BufferedImage TestImage; 
    private int cordX = 100; 
    private int cordY = 100; 

    public TestProgram() { 
     setTitle("Testing...."); 
     setSize(500, 500); 
     imageLoader(); 
     setVisible(true); 
    } 

    public void imageLoader() { 
     try { 
      String testPath = "test.png"; 
      TestImage = ImageIO.read(getClass().getResourceAsStream(testPath)); 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 

     addKeyListener(this); 
    } 

    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     g.drawImage(TestImage, cordX, cordY, this); 
    } 

    public static void main(String[] args) { 
     new TestProgram(); 
    } 


    public void keyPressed(KeyEvent ke) { 
     switch (ke.getKeyCode()) { 
      case KeyEvent.VK_RIGHT: { 
       cordX+=5; 
      } 
      break; 
      case KeyEvent.VK_LEFT: { 
       cordX-=5; 
      } 
      break; 
      case KeyEvent.VK_DOWN: { 
       cordY+=5; 
      } 
      break; 
      case KeyEvent.VK_UP: { 
       cordY-=3; 
      } 
      break; 
     } 
     repaint(); 
    } 

    public void keyTyped(KeyEvent ke) {} 

    public void keyReleased(KeyEvent ke) {} 
} 

有沒有解決方案可以避免這種情況?

編輯:上面是完整的工作代碼。我發現很難將doublebuffer加入其中。任何人都可以幫助我嗎?

+4

1)爲了更快地獲得更好的幫助,請發佈[SSCCE](http://sscce.org/)。 2)不要延長框架。 3)不要在頂層容器中繪製(比如'JFrame')而是擴展一個'JPanel' 3)設置面板的首選大小並調用'pack()'而不是設置幀的大小4)對於一個非TLC,覆蓋'paintComponent()'而不是'paint()'5)啓動並修改EDT上的GUI。 6)對於Swing應用程序,考慮使用鍵綁定而不是「KeyListener」。 7)部署時,您可能需要通過URL訪問圖像。 –

+0

@Andrew Thompson嗯,你回答了這個問題 – mKorbel

+0

@mKorbel我提供了一些提示。 (聳聳肩) –

回答

4

你必須使用緩衝區來擺脫閃爍。 對於圖像,有BufferedImage的緩衝區:

BufferedImage bf = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); 

然後你畫你的形象在屏幕上是這樣的:

g.drawImage(bf, 0, 0, null); 
+0

1)有一個時,使用'ImageObserver'而不是'null'。 2)默認情況下,Swing組件是雙緩衝的。 –

+0

謝謝!將在此工作。 – md1hunox

6

無閃爍,工作守則。

重繪()不只是調用paint()方法。 repaint()方法實際調用update()方法,然後使用默認的update()方法調用paint()方法。所以只需重寫update()方法。如上所述正確繪製爲BufferedImage。

這應該現在工作。它在這裏工作得很好。我只使用了不同的圖像路徑。

import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.JFrame; 

public class TestProgram extends JFrame implements KeyListener { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    private Image TestImage; 
    private BufferedImage bf; 
    private int cordX = 100; 
    private int cordY = 100; 

    public TestProgram() { 
     setTitle("Testing...."); 
     setSize(500, 500); 
     imageLoader(); 
     setVisible(true); 
    } 



    public void imageLoader() { 
     try { 
      String testPath = "test.png"; 
      TestImage = ImageIO.read(getClass().getResourceAsStream(testPath)); 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 

     addKeyListener(this); 
    } 

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

    public void paint(Graphics g){ 

     bf = new BufferedImage(this.getWidth(),this.getHeight(), BufferedImage.TYPE_INT_RGB); 

    try{ 
    animation(bf.getGraphics()); 
    g.drawImage(bf,0,0,null); 
    }catch(Exception ex){ 

    } 
} 

    public void animation(Graphics g) { 
     super.paint(g); 
     g.drawImage(TestImage, cordX, cordY, this); 
    } 

    public static void main(String[] args) { 
     new TestProgram(); 
    } 

    public void keyPressed(KeyEvent ke) { 
     switch (ke.getKeyCode()) { 
     case KeyEvent.VK_RIGHT: { 
      cordX += 5; 
     } 
      break; 
     case KeyEvent.VK_LEFT: { 
      cordX -= 5; 
     } 
      break; 
     case KeyEvent.VK_DOWN: { 
      cordY += 5; 
     } 
      break; 
     case KeyEvent.VK_UP: { 
      cordY -= 3; 
     } 
      break; 
     } 
     repaint(); 
    } 

    public void keyTyped(KeyEvent ke) { 
    } 

    public void keyReleased(KeyEvent ke) { 
    } 
}