Java KeyEvent方形移动

Java KeyEvent方形移动,java,swing,animation,keylistener,key-bindings,Java,Swing,Animation,Keylistener,Key Bindings,我有一段代码,当按下任何箭头键时,会触发KeyEvent。这反过来会导致正方形在屏幕上移动 现在我注意到,当我按住键时,方块会移动,但从最初的移动到后续的移动的时间相当长,如果你明白我的意思的话?这一次我该怎么做呢 谢谢 import java.awt.*; import javax.swing.*; import squarequest.sprites.*; import java.awt.event.*; public class GamePanel extends JPanel{

我有一段代码,当按下任何箭头键时,会触发KeyEvent。这反过来会导致正方形在屏幕上移动

现在我注意到,当我按住键时,方块会移动,但从最初的移动到后续的移动的时间相当长,如果你明白我的意思的话?这一次我该怎么做呢

谢谢

import java.awt.*;
import javax.swing.*;
import squarequest.sprites.*;
import java.awt.event.*;


public class GamePanel extends JPanel{

    private final int HEIGHT = 400;
    private final int WIDTH = 600;
    private Square square;
    private Circle circle;


    public GamePanel(){

        addKeyListener(new DirectionListener());

        setBackground (Color.white);
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setFocusable(true);

        square = new Square();


    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        square.display(g);

    }

    public class DirectionListener implements KeyListener{


        @Override
        public void keyReleased(KeyEvent event) {}

        @Override
        public void keyTyped(KeyEvent event) {}


        @Override
        public void keyPressed(KeyEvent event) {

            switch(event.getKeyCode()){

            case KeyEvent.VK_UP:

                square.moveUp();
                break;
            case KeyEvent.VK_DOWN:

                square.moveDown();
                break;
            case KeyEvent.VK_LEFT:

                square.moveLeft();
                break;
            case KeyEvent.VK_RIGHT:

                square.moveRight();
                break;
            }
            repaint();

        }
    }
}
  • 使用摆动计时器进行实际移动
  • 按键启动定时器
  • 释放钥匙时停止
  • 或者更好的方法是,保持计时器始终运行,但仅根据贴图的状态移动精灵,该贴图包含一个方向枚举键和一个布尔值
  • 最好使用键绑定而不是键侦听器
e、 g

import java.awt.*;
import javax.swing.*;
//!! import squarequest.sprites.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

public class GamePanel extends JPanel {
   private static final int ANIMATION_DELAY = 15;
   private final int HEIGHT = 400;
   private final int WIDTH = 600;
   private Square square;
   private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
   private Map<Integer, Direction> keyToDir = new HashMap<>();
   // !! private Circle circle;
   private Timer animationTimer;

   public GamePanel() {
      for (Direction dir : Direction.values()) {
         dirMap.put(dir, Boolean.FALSE);
      }
      keyToDir.put(KeyEvent.VK_UP, Direction.UP);
      keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
      keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
      keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
      // !! addKeyListener(new DirectionListener());
      setKeyBindings();
      setBackground(Color.white);
      setPreferredSize(new Dimension(WIDTH, HEIGHT));
      setFocusable(true);
      square = new Square();
      animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
      animationTimer.start();
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      final InputMap inputMap = getInputMap(condition);
      final ActionMap actionMap = getActionMap();
      boolean[] keyPressed = { true, false };
      for (Integer keyCode : keyToDir.keySet()) {
         Direction dir = keyToDir.get(keyCode);
         for (boolean onKeyPress : keyPressed) {
            boolean onKeyRelease = !onKeyPress; // to make it clear how bindings work
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
                  onKeyRelease);
            Object key = keyStroke.toString();
            inputMap.put(keyStroke, key);
            actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
         }
      }
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      square.display(g);
   }

   // public class DirectionListener implements KeyListener {
   // @Override
   // public void keyReleased(KeyEvent event) {
   // int keyCode = event.getKeyCode();
   // if (keyToDir.keySet().contains(keyCode)) {
   // Direction dir = keyToDir.get(keyCode);
   // dirMap.put(dir, false);
   // }
   // }
   //
   // @Override
   // public void keyTyped(KeyEvent event) {
   // }
   //
   // @Override
   // public void keyPressed(KeyEvent event) {
   // int keyCode = event.getKeyCode();
   // if (keyToDir.keySet().contains(keyCode)) {
   // Direction dir = keyToDir.get(keyCode);
   // dirMap.put(dir, true);
   // }
   // }
   // }

   private class AnimationListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent evt) {
         boolean repaint = false;
         for (Direction dir : Direction.values()) {
            if (dirMap.get(dir)) {
               square.move(dir);
               repaint = true;
            }
         }
         if (repaint) {
            repaint();
         }
      }
   }

   private class KeyBindingsAction extends AbstractAction {
      private Direction dir;
      boolean pressed;

      public KeyBindingsAction(Direction dir, boolean pressed) {
         this.dir = dir;
         this.pressed = pressed;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         dirMap.put(dir, pressed);
      }
   }

   private static void createAndShowGUI() {
      GamePanel gamePanel = new GamePanel();
      JFrame frame = new JFrame("GamePanel");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(gamePanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      gamePanel.requestFocusInWindow();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}

enum Direction {
   UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
   private int incrX;
   private int incrY;

   private Direction(int incrX, int incrY) {
      this.incrX = incrX;
      this.incrY = incrY;
   }

   public int getIncrX() {
      return incrX;
   }

   public int getIncrY() {
      return incrY;
   }
}

class Square {
   private int x = 0;
   private int y = 0;
   private int w = 20;
   private int h = w;
   private int step = 1;
   private Color color = Color.red;
   private Color fillColor = new Color(255, 150, 150);
   private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
         BasicStroke.JOIN_ROUND);

   public void display(Graphics g) {
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.setColor(fillColor);
      g2d.fillRect(x, y, w, h);
      g2d.setStroke(stroke);
      g2d.setColor(color);
      g2d.drawRect(x, y, w, h);
      g2d.dispose();
   }

   public void setStep(int step) {
      this.step = step;
   }

   public void move(Direction dir) {
      x += step * dir.getIncrX();
      y += step * dir.getIncrY();
   }

//   public void moveRight() {
//      x++;
//   }
//
//   public void moveLeft() {
//      x--;
//   }
//
//   public void moveUp() {
//      y--;
//   }
//
//   public void moveDown() {
//      y++;
//   }
}
import java.awt.*;
导入javax.swing.*;
//!! 导入squarequest.sprites.*;
导入java.awt.event.*;
导入java.util.EnumMap;
导入java.util.HashMap;
导入java.util.Map;
公共类游戏面板扩展了JPanel{
专用静态最终int动画_延迟=15;
私人最终内部高度=400;
专用最终整数宽度=600;
私人广场;
私有EnumMap dirMap=新EnumMap(Direction.class);
private Map keytdir=新建HashMap();
//!!私人圈子;
私人定时器动画定时器;
公共游戏小组(){
for(Direction dir:Direction.values()){
dirMap.put(dir,Boolean.FALSE);
}
keyToDir.put(KeyEvent.VK_UP,Direction.UP);
keyToDir.put(KeyEvent.VK_DOWN,Direction.DOWN);
keyToDir.put(KeyEvent.VK_左,Direction.LEFT);
keyToDir.put(KeyEvent.VK_RIGHT,Direction.RIGHT);
//!!addKeyListener(新的DirectionListener());
setKeyBindings();
挫折地面(颜色:白色);
setPreferredSize(新尺寸(宽度、高度));
设置聚焦(真);
正方形=新正方形();
animationTimer=新计时器(ANIMATION_DELAY,new AnimationListener());
animationTimer.start();
}
私有void setKeyBindings(){
int condition=当在聚焦窗口中时;
最终InputMap InputMap=getInputMap(条件);
final ActionMap ActionMap=getActionMap();
布尔[]键按下={true,false};
for(整数键代码:keyToDir.keySet()){
Direction dir=keyToDir.get(keyCode);
用于(布尔onKeyPress:keyPressed){
布尔值onKeyRelease=!onKeyPress;//以明确绑定的工作方式
击键击键=击键。getKeyStroke(键代码,0,
onKeyRelease);
Object key=keyStroke.toString();
inputMap.put(击键,键);
put(key,newkeybindingsaction(dir,onKeyPress));
}
}
}
公共组件(图形g){
超级组件(g);
方形显示器(g);
}
//公共类DirectionListener实现KeyListener{
//@覆盖
//公共无效密钥已释放(KeyEvent事件){
//int keyCode=event.getKeyCode();
//if(keyToDir.keySet().包含(keyCode)){
//Direction dir=keyToDir.get(keyCode);
//dirMap.put(dir,false);
// }
// }
//
//@覆盖
//public void keyTyped(KeyEvent事件){
// }
//
//@覆盖
//按下公共无效键(KeyEvent事件){
//int keyCode=event.getKeyCode();
//if(keyToDir.keySet().包含(keyCode)){
//Direction dir=keyToDir.get(keyCode);
//dirMap.put(dir,true);
// }
// }
// }
私有类AnimationListener实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件evt){
布尔重绘=假;
for(Direction dir:Direction.values()){
if(dirMap.get(dir)){
方。移动(直接);
重新绘制=真;
}
}
如果(重新喷漆){
重新油漆();
}
}
}
私有类KeyBindingsAction扩展了AbstractAction{
私人指导主任;
布尔按下;
公钥绑定操作(方向方向,按布尔值){
this.dir=dir;
this.pressed=pressed;
}
@凌驾
已执行的公共无效操作(操作事件evt){
dirMap.put(dir,按下);
}
}
私有静态void createAndShowGUI(){
GamePanel GamePanel=新建GamePanel();
JFrame=新JFrame(“游戏面板”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(游戏面板);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
gamePanel.requestFocusInWindow();
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
枚举方向{
向上(0,-1),向下(0,1),左(-1,0),右(1,0);
私人int incrX;
私营企业;
私人方向(内部控制,内部控制){
this.incrX=incrX;
this.incrY=incrY;
}
public int getIncrX(){
返回incrX;
}
public int getIncrY(){
返回incrY;
}
}
阶级广场{
私有整数x=0;
私有整数y=0;
私人int w=20;
私有int h=w;
私有整数步长=1;
私有颜色=Color.red;
私有颜色fillColor=新颜色(255、150、150);
私人行程行程=新的基本行程(3f,基本行程,
基本行程。加入(轮);
公共空间显示(图形g){
Graphics2D g2d=(Graphics2D)g.create();
g2d.setColor(fillColor);
g2d.fillRect(x,y,w,h);
g2d.设定行程(行程);
g2d.setColor(彩色);
g2d.drawRect(x,y,w,h);
g2d.dispose();
}
公共无效设置步骤(内部步骤){
这个步骤=步骤;
}
公共无效移动(方向目录){
x+=步骤*dir.getIncrX();
y+=步骤*dir.getIncrY();
}
//公权{
//x++;
//   }
//
//公共无效动议