2013-06-04 86 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