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

如何在Java Swing代码中实现无延迟的流畅键盘控制移动效果

问题根源

你遇到的停顿是操作系统按键触发机制导致的:系统默认按住按键时,第一次触发keyPressed事件后,会有数百毫秒的初始延迟才会连续触发重复事件,切换按键时也需要等待新按键的事件触发,所以出现转向卡顿。

解决思路

我们改用状态轮询的方式替代直接在按键事件中移动控件:

  • 定义4个布尔变量分别记录上下左右方向键的按下状态
  • 按键事件回调仅负责更新对应按键的状态,不直接操作控件位置
  • 启动一个Swing定时器固定间隔刷新控件位置,直接读取当前按键状态计算新坐标,完全避开系统按键延迟
完整修改代码
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;

class MyFrame extends JFrame implements KeyListener {
    JLabel label;
    // 记录四个方向键的按下状态
    boolean upPressed, downPressed, leftPressed, rightPressed;
    // 移动步长,可自行调整
    int step = 10;

    MyFrame(){ 
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addKeyListener(this);
        // 注意Windows路径要转义反斜杠,或者用正斜杠:C:/Users/jacob/Downloads/player.png
        ImageIcon imageIcon = new ImageIcon("C:\\Users\\jacob\\Downloads\\player.png");
        
        Image image = imageIcon.getImage();
        Image newimg = image.getScaledInstance(150, 150,  java.awt.Image.SCALE_SMOOTH);
        imageIcon = new ImageIcon(newimg);
        label = new JLabel(imageIcon);
        this.add(label);
        this.setSize(500, 500);
        this.setVisible(true);

        // 启动60帧刷新的定时器,每16ms更新一次位置
        Timer moveTimer = new Timer(16, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int x = label.getX();
                int y = label.getY();
                if(upPressed) y -= step;
                if(downPressed) y += step;
                if(leftPressed) x -= step;
                if(rightPressed) x += step;
                label.setLocation(x, y);
            }
        });
        moveTimer.start();
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
        // 仅更新按键状态,不直接移动
        switch (e.getKeyCode()) {
            case KeyEvent.VK_UP -> upPressed = true;
            case KeyEvent.VK_DOWN -> downPressed = true;
            case KeyEvent.VK_LEFT -> leftPressed = true;
            case KeyEvent.VK_RIGHT -> rightPressed = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // 松开按键时更新状态
        switch (e.getKeyCode()) {
            case KeyEvent.VK_UP -> upPressed = false;
            case KeyEvent.VK_DOWN -> downPressed = false;
            case KeyEvent.VK_LEFT -> leftPressed = false;
            case KeyEvent.VK_RIGHT -> rightPressed = false;
        }
    }
}
额外说明

修改后不仅解决了转向延迟的问题,还支持同时按下两个方向键实现斜向移动,流畅度大幅提升。如果觉得移动速度不合适,可以调整step变量的数值,或者修改定时器的间隔时间。

内容的提问来源于stack exchange,提问作者Jacob Ptak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:09:02