2013-06-04 87 views
0

我只是在爲我的java2d遊戲創建一個多線程渲染器的想法,其中每個線程負責渲染其自己的swingcomponent並提出了一個簡單的程序來嘗試並實現此目的。多線程渲染擺動

*我知道了Thread.sleep不是首選方法,但它已經 工作沒有在我的使用 活躍渲染單線程渲染順利,我沒有用swingtimer但我 知識測試Thread.sleep睡眠調用線程,以便不能成爲 的問題。

問題)該程序創建四個線程四個小組,在每一個反彈球,但只有第一個創建的線程永遠做任何事情,其他人都簡單地根本不啓動(查證在運行方法SYSOUT)。因此,只有一個線程執行渲染,而其他線程無法運行,sysout:System.out.println("Ballbouncer: " + this + " running.");證實了這一點,視覺效果也是如此(圖像添加)。

BallBouncer(可運行)

public class BallBouncer implements Runnable { 
private ColoredPanel ballContainer; 
private List<Ellipse2D.Double> balls; 
public static final Random rnd = new Random(); 
private double speedX, speedY; 

public BallBouncer(ColoredPanel container) { 
    this.ballContainer = container; 
    this.balls = new ArrayList<>(); 
    balls.add(container.getBall()); 
    this.speedX = 10 * rnd.nextDouble() - 5; 
    this.speedY = 10 * rnd.nextDouble() - 5; 
} 

public BallBouncer(List<ColoredPanel> containers) { 
    for (ColoredPanel p : containers) { 
     new BallBouncer(p).run(); 
    } 
} 

@Override 
public void run() { 
    while (true) { 
     System.out.println("Ballbouncer: " + this + " running."); 
     moveBall(); 
     ballContainer.repaint(); 
     try { 
      Thread.sleep(15); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

private void moveBall() { 
    for (Ellipse2D.Double ball : balls) { 
     ball.x += speedX; 
     ball.y += speedY; 

     if (ball.x < 0 
       || ball.x + ball.getWidth() > ballContainer.getWidth()) { 
      speedX *= -1; 
     } 
     if (ball.y < 0 
       || ball.y + ball.getHeight() > ballContainer.getHeight()) { 
      speedY *= -1; 
     } 
    } 


} 

集裝箱

public class ColoredPanel extends JPanel { 
private Ellipse2D.Double circle; 

public ColoredPanel(Color color) { 
    circle = new Ellipse2D.Double(0, 0, 10, 10); 
    setBackground(color); 
} 

public Ellipse2D.Double getCircle() { 
    return circle; 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2d = (Graphics2D) g.create(); 
    g2d.setColor(getBackground().darker()); 
    g2d.fill(circle); 
} 

@Override 
@Transient 
public Dimension getPreferredSize() { 
    return new Dimension(400, 400); 
} 

public Double getBall() { 
    return getCircle(); 
} 

主要

public class ColoredPanelContainer extends JPanel { 

private List<ColoredPanel> panels = new ArrayList<>(); 

public ColoredPanelContainer() { 
    setUpPanels(); 
    setBackground(Color.black); 
} 

private void setUpPanels() { 
    for (int i = 0; i < 4; i++) { 
     Color color = new Color(BallBouncer.rnd.nextInt(256), 
       BallBouncer.rnd.nextInt(256), BallBouncer.rnd.nextInt(256)); 
     panels.add(new ColoredPanel(color)); 
    } 
    for (int i = 0; i < 4; i++) { 
     add(panels.get(i)); 
    } 
} 

@Override 
@Transient 
public Dimension getPreferredSize() { 
    return new Dimension(1000, 1000); 
} 

public List<ColoredPanel> getPanels() { 
    return panels; 
} 

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    ColoredPanelContainer container = new ColoredPanelContainer(); 
    frame.getContentPane().add(container); 
    frame.pack(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
    new BallBouncer(container.getPanels()); 
} 
} 

注意球只在左側面板彈跳(第一次啓動線程),其他都是固定的每時每刻。 enter image description here

+0

您有問題嗎? –

+0

是的,只有一個線程在進行渲染,其他線程從來沒有開始過(我在問題描述中可能有點不清楚,會編輯,謝謝) – arynaq

+0

這是一個聲明......不是一個問題。 –

回答

4

你這樣做:

public BallBouncer(List<ColoredPanel> containers) { 
    for (ColoredPanel p : containers) { 
     new BallBouncer(p).run(); 
    } 
} 

這並不是啓動一個線程的正確方法。你所要做的就是直接運行run方法,然後依次運行。這意味着代碼在調用構造函數的同一個線程中的循環中運行。

You should read this tutorial.它解釋瞭如何在Swing中使用線程。即,如何使用javax.swing.SwingWorkerSwingUtilities.invoke*There is also this tutorial,它解釋瞭如何使用Swing Timer類。

而且,只是爲了進一步教育線程:Here are ways to start threads in java when you're not using swing當您正在編寫Swing應用程序時,您不想使用這些示例

+0

嗯謝謝你將這個runnable包裝在一個新的Thread中,並啓動它使得所有四個面板中的球都反彈了,我感到在runnable上調用.run會啓動它作爲一個新線程。當談到鞦韆和EDT時,我感到有些緊張,當我嘗試創建一款遊戲時,我首先進入了鞦韆,並且主動渲染更加方便和強大,以滿足我的需求。我還沒有看到一個很好的解釋,當你採取主動渲染時,EDT做了什麼,我知道一些java2d遊戲使用多線程與主動渲染,並且很少依賴於swing的併發。 – arynaq

+0

@arynaq正如我剛纔所說的,你不想做你剛做的事情。根據您的需要,改用SwingWorker或Timer。 –

+0

謝謝,我知道,這對我來說很有用,直到我能夠完全說服自己,它應該沒有完成,尋找一個關於swing併發性的詳細資源,這個教程很好,但它並沒有解釋如何構建東西因此我可能會如何設法打破它。我甚至不知道如何在後臺完成渲染,如果我在一千個內核上產生了一千個線程(如果java有一個線程正在對圖形管道進行實際渲染),它會影響嗎?我還不知道的事情!無論如何感謝您的警告。 – arynaq