我已经有一篇与多线程问题相关的帖子,但我有一些新的问题+代码。我有一个多球游戏项目,它需要我解析 XML 文件以获取有关球的信息(如大小、速度、初始位置等)。现在,我想创建一个不同的线程来解析 XML 文件,但我不知道如何做到这一点。这是我的代码:
main() 从这里开始:
public class BounceBallApp extends JFrame{
public BounceBallApp()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("BounceBallApp");
setSize(300,300);
setVisible(true);
add(new BallWorld());
validate();
}
public static void main(String[] args)
{
/*Create main GUI in the Event Dispatch Thread*/
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new BounceBallApp(); //main frame
}
});
}
}
在 BallWorld() 的构造函数中,我有一个内部类 BallContainer(),其中包含一个“开始”按钮:
jbtStart.addActionListener(new ActionListener()
{public void actionPerformed(ActionEvent e)
{
//Populate the ballList arraylist
if(filePathField.getText().equals(" "))
{
JOptionPane.showMessageDialog(null, "Please input the XML file","Information", JOptionPane.INFORMATION_MESSAGE);
}
else
{
XMLFilePath = filePathField.getText();
ballList = new BallList(XMLFilePath);//I want to put this in a thread
JOptionPane.showMessageDialog(null,"Game started!","Bouncing Balls",JOptionPane.INFORMATION_MESSAGE);
for(Ball ball:ballList.ballsArrayList)
{
timer.setDelay(1000/ball.getSpeed()); //change the delay of the timer to the ball's speed
timer.start(); //start the timer
bTimer = true; //timer is now on
}
}
}
});
}
现在的问题是,如果我将解析过程放在另一个线程中,那么我必须等待 ballsArrayList 填满才能继续应用程序。我正在考虑使用 invokeAndWait() 但我读到无法从事件调度线程调用该方法。那么,我怎样才能实现这一目标呢?或者说这是否值得? 另外,我想将移动球的计算(计算 x,y 坐标)移至线程,但同样,我不知道如何实现它。
for(Ball ball:ballList.ballsArrayList)
{
ball.draw(g);
ball.move(ballContainerWidth,ballContainerHeight,buttonPanel.getHeight());
}
public void move(int ballContainerWidth,int ballContainerHeight,int buttonPanelHeight)
{
if((this.getX()+this.getsize()+this.getDx()) > ballContainerWidth)
{
this.setDx(-Math.abs(this.getDx()));
}
//the height/depth to which the balls can bounce is the (main ball container height) minus (button panel height)
if((this.getY()+this.getsize()+this.getDy()) > ballContainerHeight-buttonPanelHeight)
{
this.setDy(-Math.abs(this.getDy()));
}
if((this.getX()-this.getsize()) < 0 )
{
this.setDx(Math.abs(this.getDx()));
}
if((this.getY()-this.getsize()) < 0 )
{
this.setDy(Math.abs(this.getDy()));
}
int newX = (int)Math.round((this.getX()+this.getDx()));
int newY = (int)Math.round((this.getY()+this.getDy()));
this.setX(newX);
this.setY(newY);
}
很抱歉这篇文章很长,但多线程对我来说是全新的。我对此有点困惑。
最佳答案
文件的初始加载
我个人会选择以下方法之一
- 通过在启动期间解析所有文件来增加程序的启动时间。对于一些 XML 文件来说,这个开销可能非常小。如果时间太长,可以考虑显示splash screen
- 按下开始按钮时加载 XML 文件,但在加载完成之前显示进度条。之后开始游戏。
SwingWorker
可以帮助您完成此任务。示例可以在 Swing documentation 中找到。或here on SO .
更新球位置
如果计算像此处所示的那样简单,我只需使用 javax.swing.Timer
定期更新位置,并在事件调度线程上进行计算.
如果您只是为了练习而想在后台线程上进行计算,我仍然会选择在后台线程上计算位置。计算应该使用只有该后台线程知道的局部变量。计算出新位置后,使用 SwingUtilities#invokeLater
更新事件调度线程上球的位置。这使您可以在 paint
操作期间访问该位置,而不必担心线程问题。可能比乱搞锁更容易。
关于java - 多线程 Swing 事件调度程序线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13208668/