我有一个关于Swing Timer的问题,特别是如何多次调用actionPerformed
并等待最后actionPerformed
完成再次执行之前。我知道其他人之前已经问过这个问题,但我找到的解决方案都没有适用于我的程序。
继承我所拥有的:
我试图沿着从一个位置到另一个位置的路径使用Square对象(矩形)。路径以方形对象数组的形式给出(使用A *发现路径,路径中的所有方块都添加到ArrayList
)。 actionPerformed
方法将方块从当前的x,y位置移动到下一个位置,接下来是我提到路径中的下一个方块。例如:
开始(移动方块)位于x 200,y 50 结束(目标方格)为x 300,y 150 到这个位置的路径中的方块是(在x,y位置): (250,50),(300,50),(300,100),(300,150)
但是不是一次移动一个方格,移动的方块将如下所示移动:(采用快捷方式)。
我相信原因是计时器没有等待actionPerformed
完成,所以在广场开始移动之前,听众已经收到最后一个方格(300,150)作为目标,然后移动的广场直接移动到那里..
这是我的一些代码:
MovementListener(保持actionPerformed)
public MovementListener(Canvas canvas){
this.canvas = canvas;
}
public void setSquares(Square moving, Square target){
this.moving = moving;
this.target = target;
}
@Override
public void actionPerformed(ActionEvent e) {
// I tried adding a boolean here, to indicate if the action is finished or not, what I tried was:
// setRunning(true); (set to false below, see at the end of this method)
if (this.moving.getX() < this.target.getX()){
moving.setLocation((int)(moving.getX() + 10), (int)(moving.getY()));
this.canvas.repaint();
}
if (this.moving.getY() < this.target.getY()){
moving.setLocation((int)(moving.getX()), (int)(moving.getY() + 10));
this.canvas.repaint();
}
// setRunning(false);
}
这是包含监听器和计时器的类:
public Canvas(){
// setup ActionListener
listener = new MovementListener(this);
timer = new Timer(100, listener);
}
public void startTimer(Square moving, Square target){
// I tried using the isRunning variable here, so that the next actionPerformed doesn't get called unless listener is ready
if (listener.isReady()){
listener.setSquares(moving, target);
timer.start();
}
}
以下是移动操作开始的代码(上面定义了Square moving
)。此外,向后for循环是正确的,路径ArrayList
是相反的顺序(位置0的最后一个方格,列表末尾的路径的开头):
for (int i = controller.getPath().size()-1; i >= 0; i--){
Square target = controller.getPath().get(i);
canvas.startTimer(moving, target);
}
任何帮助将不胜感激!我现在一直试图解决这个问题几个小时了...... 谢谢:))
编辑: 好吧,我按照camickr描述的方式开始工作:
新的actionPerformed
@Override
public void actionPerformed(ActionEvent e) {
Square current = controller.getPath().get(0);
if (this.moving.getX() < current.getX()){
moving.setLocation((int)(moving.getX() + 10), (int)(moving.getY()));
this.canvas.repaint();
}
if (this.moving.getY() < current.getY()){
moving.setLocation((int)(moving.getX()), (int)(moving.getY() + 10));
this.canvas.repaint();
} else {
controller.getPath().remove(current);
}
if (controller.getPath().isEmpty()){
canvas.getTimer().stop();
}
}
现在正在运作!
答案 0 :(得分:1)
for (int i = controller.getPath().size()-1; i >= 0; i--){
Square target = controller.getPath().get(i);
canvas.startTimer(moving, target);
}
在上面的代码中,您遍历设置Square位置的循环。方形位置在Timer有机会发射之前设置为结束位置,因此您只能看到在最后位置绘制的方形。
使用Timer时,不需要使用循环。 Timer取代了循环。你只需启动计时器。然后当Timer触发你做某事时。
所以,你的逻辑就像是: