You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在计时器运行时禁用键盘输入?解决角色移动按键冲突问题

解决方案

核心思路

用一个布尔变量标记角色是否处于移动状态,移动过程中直接忽略所有键盘输入;同时过滤非方向键的按键事件,避免无关操作触发故障。

具体实现步骤

  1. 添加全局布尔标志位,控制输入锁定:
private boolean isMoving = false; // 标记是否正在移动
  1. 修改moveCharacter方法,先检查移动状态,再处理方向键,直接忽略其他按键:
@FXML
public void moveCharacter(KeyEvent event) {
    // 正在移动时直接返回,忽略所有输入
    if (isMoving) {
        return;
    }
    
    KeyCode code = event.getCode();
    // 只处理方向键,其他按键直接忽略
    if (!code.equals(KeyCode.D) && !code.equals(KeyCode.RIGHT) && !code.equals(KeyCode.A) && !code.equals(KeyCode.LEFT)) {
        return;
    }

    switch (code) {
        case D, RIGHT:
            try {
                moveForward();
            } catch (URISyntaxException | InterruptedException e) {
                throw new RuntimeException(e);
            }
            break;
        case A, LEFT:
            try {
                moveBack();
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
            break;
    }
}
  1. 修改moveForward和moveBack方法,在Timer调度移动的前后更新isMoving状态,确保移动完成后解锁输入:
private void moveForward() throws URISyntaxException {
    isMoving = true; // 开始移动,锁定输入
    Timer timer = new Timer();
    TimerTask task = new TimerTask() {
        int steps = 0;
        final int totalSteps = 10; // 假设移动需要10步完成

        @Override
        public void run() {
            if (steps < totalSteps) {
                // 执行每一步的移动逻辑,比如修改角色坐标
                character.setX(character.getX() + 5);
                steps++;
            } else {
                timer.cancel();
                isMoving = false; // 移动完成,解锁输入
            }
        }
    };
    timer.scheduleAtFixedRate(task, 0, 50); // 每50ms执行一步
}

// moveBack方法同理,只需修改移动方向
private void moveBack() throws URISyntaxException {
    isMoving = true;
    Timer timer = new Timer();
    TimerTask task = new TimerTask() {
        int steps = 0;
        final int totalSteps = 10;

        @Override
        public void run() {
            if (steps < totalSteps) {
                character.setX(character.getX() - 5);
                steps++;
            } else {
                timer.cancel();
                isMoving = false;
            }
        }
    };
    timer.scheduleAtFixedRate(task, 0, 50);
}

为什么之前的方案无效?

  • 时间阈值方案:Timer的异步执行和按键事件的触发是独立的,可能在Timer还没完成时,时间阈值已经满足,导致新的输入被处理,冲突引发故障。
  • Thread.sleep:JavaFX的UI操作必须在主线程执行,sleep会阻塞主线程,导致所有UI更新被延迟到sleep结束后一次性执行,看起来像瞬移。

内容的提问来源于stack exchange,提问作者Zhe Hin Yap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:20