沿路径移动对象:如何在上一个actionPerformed完成后调用actionPerformed?

时间:2018-03-21 16:01:29

标签: java swing timer

我有一个关于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)

enter image description here

但是不是一次移动一个方格,移动的方块将如下所示移动:(采用快捷方式)。

enter image description here

我相信原因是计时器没有等待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();
    }
}

现在正在运作!

1 个答案:

答案 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触发你做某事时。

所以,你的逻辑就像是:

  1. 将Square对象添加到ArrayList
  2. 启动计时器
  3. 当调用ActionListener时,a)从ArrayList获取第一个Square b)将对象移动到正方形c)从ArrayList中删除Square
  4. 当ArrayList为空时,您将停止计时器。