gpt4 book ai didi

java - 沿着路径移动对象: How to call actionPerformed only after previous actionPerformed has finished?

转载 作者:行者123 更新时间:2023-12-02 11:29:10 27 4
gpt4 key购买 nike

我有一个关于 Swing Timer 的问题,特别是如何多次调用 actionPerformed 并等待最后一个 actionPerformed 完成后再执行它。我知道其他人以前也问过这个问题,但我发现没有一个解决方案适合我的程序。

这是我所拥有的:我正在尝试沿从一个位置到另一个位置的路径使用方形对象(矩形)。路径以正方形对象数组的形式给出(路径是使用 A* 发现的,路径中的所有正方形都添加到 ArrayList 中)。 actionPerformed 方法将方 block 从当前的 x、y 位置移动到下一个位置,下一个是我提到的路径中的下一个方 block 。例如:

起点(移动方 block )位于 x 200,y 50终点(目标方格)位于 x 300,y 150到达该位置的路径中的方 block 为(在 x、y 位置):(250, 50), (300, 50), (300, 100), (300, 150)

enter image description here

但是移动的方 block 不是一次移动一个方 block ,而是如下所示移动:(走捷径)。

enter image description here

我相信原因是计时器没有等待 actionPerformed 完成,因此在方 block 开始移动之前,监听器已经接收到最后一个方 block (300, 150) 作为目标,然后移动方 block 直接移动到那里..

这是我的一些代码:

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();
}
}

这是移动 Action 开始的代码(上面定义了 Square moving)。另外,向后的 for 循环是正确的,路径 ArrayList 是相反的顺序(最后一个方 block 位于位置 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();
}
}

现在可以了!

最佳答案

for (int i = controller.getPath().size()-1; i >= 0; i--){
Square target = controller.getPath().get(i);
canvas.startTimer(moving, target);
}

在上面的代码中,您迭代设置 Square 位置的循环。在计时器有机会触发之前,正方形位置就设置为末尾,因此您只能看到绘制在最后一个位置的正方形。

当您使用计时器时,您不需要使用循环。定时器取代了循环。您只需启动计时器即可。然后,当计时器触发时,您将执行某些操作。

所以,你的逻辑会是这样的:

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

关于java - 沿着路径移动对象: How to call actionPerformed only after previous actionPerformed has finished?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49411148/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com