2016-11-09 67 views
0

我正試圖做一個簡單的程序,其中一個球通過JFrame中的Canvas移動。 我想讓主線程更新屏幕中球的位置並在畫布上打印每一幀,而另一個線程更新緩衝區上的每個下一幀。這是我的代碼:如何使用多個線程創建緩衝平滑動畫?

public class SynchAnimation { 

private JFrame frame; 
private Canvas canvas; 
private BufferedImage frameImage; 
private Graphics bfg; 
private final int width = 500, height = 500; 
private int x, y; 
private DrawingThread drawingThread; 
private final Object key; 

public SynchAnimation() { 

    key = new Object(); 

    x = 200; 
    y = 200; 

    frame = new JFrame("Synchronized animation"); 
    frame.setSize(width, height); 
    frame.setLocationRelativeTo(null); 

    frameImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
    bfg = frameImage.createGraphics(); 

    canvas = new Canvas() { 
     @Override 
     public void paint(Graphics g) { 
      g.drawImage(frameImage, 0, 0, null); 
     } 
    }; 
    canvas.setSize(width, height); 

    frame.add(canvas); 
    frame.pack(); 
    frame.setVisible(true); 
} 

public void mainRun() { 

    drawingThread = new DrawingThread(); 
    drawingThread.start(); 

    while (true) { 
     synchronized (key) { 
      x += 1; 
      y += 1; 
      canvas.repaint(); 
     } 
    } 
} 

class DrawingThread extends Thread { 

    @Override 
    public void run() { 
     while (true) { 
      synchronized (key) { 
       bfg.clearRect(0, 0, width, height); 
       bfg.setColor(Color.BLUE); 
       bfg.fillRect(0, 0, width, height); 
       bfg.setColor(Color.ORANGE); 
       bfg.fillOval(x, y, 40, 40); 
      } 
     } 
    } 
} 

public static void main(String[] args) { 
    new SynchAnimation().mainRun(); 
} 

爲什麼它仍然閃爍着地獄?我認爲同步塊會做伎倆。這實際上不是一個GUI問題,而是一個線程問題......我這樣做是爲了理解嘗試訪問和修改相同數據時同步線程是如何工作的。 感謝您的幫助!

+1

我很震驚,這種即使sorta工程。你不會開始畫一個線程 - 你重寫組件的'paint()'和/或'update()'方法。 GUI工具包是基於事件的,並且這些應用程序有一個結構。有關Swing組件/事件流程/繪圖的概述,請參閱https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html。 – BadZen

+1

此外,您應該知道,語言規範對線程獲取監視器鎖定的順序絕對沒有任何要求(從「synchronized」開始 - 對於其中一個循環而言,完全有效的行爲永遠不會運行,方式你已經編碼了,從我鏈接的線索和C&P的示例項目開始,然後從那裏修改,示例代碼是完全錯誤的。=/ – BadZen

+0

作爲附加註釋同步使用什麼:爲了防止同時訪問在這個區塊中,並行訪問是不可能的,因此會從單獨的線程中獲得任何好處,只能在關鍵部分使用它們(例如:訪問資源) – Gildraths

回答

0

你可能想重載paintComponent()而不是