Java使用Swing同步线程
我写了一个程序,它在窗口中显示球,球在移动,在接触时以一定的概率相互吸收 当前版本有效,每次(隐式)调用paintComponent方法时都会计算球的运动:Java使用Swing同步线程,java,multithreading,swing,Java,Multithreading,Swing,我写了一个程序,它在窗口中显示球,球在移动,在接触时以一定的概率相互吸收 当前版本有效,每次(隐式)调用paintComponent方法时都会计算球的运动: 我的问题是我不知道如何同步球的绘制和运动计算?ColliderPanel甚至需要线程作为成员吗?我刚刚找到了关于如何同步调用同一方法的两个线程的教程,但我想在这里做什么?这看起来像经典的生产者-消费者场景。计算球运动的线程是生产者,绘制球运动的线程是消费者。查看以下主题的教程:或这看起来像经典的生产者-消费者场景。计算球运动的线程是生产者,
我的问题是我不知道如何同步球的绘制和运动计算?
ColliderPanel
甚至需要线程作为成员吗?我刚刚找到了关于如何同步调用同一方法的两个线程的教程,但我想在这里做什么?这看起来像经典的生产者-消费者场景。计算球运动的线程是生产者,绘制球运动的线程是消费者。查看以下主题的教程:或这看起来像经典的生产者-消费者场景。计算球运动的线程是生产者,绘制球运动的线程是消费者。查看以下关于主题的教程:或使用Swing需要记住的主要一点是,除了Swing事件调度线程(EDT),几乎不应从任何其他线程调用Swing方法
EDT是处于循环中的东西,它等待按键、鼠标单击和其他事件,并在每次程序感兴趣的事件发生时调用处理程序
当您的任何其他线程想要执行会影响GUI的操作时,它应该调用
SwingUtilities.invokeLater(r)
方法,其中r
是一些Runnable
对象。invokeLater(r)方法将包含r
的事件发布到事件队列,EDT将通过调用r.run()
来处理该事件。然后,r.run()方法可以安全地调用您需要它调用的任何Swing方法。使用Swing需要记住的一点是,除了Swing事件调度线程(EDT),几乎不应从任何其他线程调用任何Swing方法
EDT是处于循环中的东西,它等待按键、鼠标单击和其他事件,并在每次程序感兴趣的事件发生时调用处理程序
当您的任何其他线程想要执行会影响GUI的操作时,它应该调用
SwingUtilities.invokeLater(r)
方法,其中r
是一些Runnable
对象。invokeLater(r)方法将包含r
的事件发布到事件队列,EDT将通过调用r.run()
来处理该事件。r.run()方法可以安全地调用您需要它调用的任何Swing方法。一个建议是将计算移到swingworkers后台处理方法中,并在worker的done方法中调用repaint。一个建议是将计算移到swingworkers后台处理方法中,并在done中调用repaint工人的方法。阅读本教程:避免在paintComponent(Graphics g)
内部调用repaint()
将计算外包给另一个线程的任何特定原因?Chris K谢谢,我会看看这个@阿文德,为什么我不能那样做?{at}acearch的主要原因是一个教育性的原因,但事先我认为当将来计算变得更复杂时,最好在另一个线程中进行计算。阅读本教程:避免调用repaint()
insidepaintComponent(图g)
将计算外包给另一个线程有什么特殊原因吗?Chris K谢谢,我来看看这个@阿文德,为什么我不能那样做?{at}acearch的主要原因是一个教育性的原因,但事先我认为,当它在将来变得更复杂时,最好在另一个线程中进行计算。
public class ColliderPanel extends JPanel {
...
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
// calculate balls's movement
Random r = new Random();
ListIterator<Ball> it = cp.getColliderPanel().balls.listIterator();
Vector<Ball> ballsToRemove = new Vector<Ball>();
while (it.hasNext()) {
Ball b = it.next();
b.move(1.0 / 60.0);
b.collideFrame(cp.getColliderPanel().getSize());
ListIterator<Ball> it2 = cp.getColliderPanel().balls.listIterator(it.nextIndex());
while (it2.hasNext()) {
Ball b2 = it2.next();
if (b.collide(b2)) {
if (r.nextDouble() < 0.5) {
if (b.m > b2.m) {
b.swallow(b2);
ballsToRemove.add(b2);
} else {
b2.swallow(b);
ballsToRemove.add(b);
}
}
}
}
}
cp.getColliderPanel().balls.removeAll(ballsToRemove);
try {
Thread.sleep((long) (1000.0 / 60.0));
} catch (InterruptedException e) {
e.printStackTrace();
}
for(Ball b : balls) b.draw(g);
repaint();
}
...
}
public class ColliderPanel extends JPanel {
private Thread simThread = new Thread(new SimulateBallsMovement());
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
// calculate balls's movement
// what to to here? how to synchronize the painting and the calculation?
for(Ball b : balls) b.draw(g);
repaint();
}
...
}