2015-02-10 33 views
0

我创建了一个JFrame,它的中心有一个矩形,当我按下某些键时,该矩形会移动。这一切都很好,并且很棒,但是当我释放钥匙时矩形继续前进。事实上,如果我多次按下某个键,矩形会加速。这可能是(绝对),因为我使用计时器来解决按住按键时那个令人讨厌的0.5秒输入延迟。如何在释放移动它的键时让矩形停止?

我想我必须把东西放在keyReleased()的方法,但我不知道该放什么东西。有小费吗?谢谢。

PS:不要因为没有使用密钥绑定而大叫我。我知道:他们是更好的东西。但我现在专注于关键听众。

计划:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.Timer; 

@SuppressWarnings ("serial") 
public class GameFrame extends JComponent implements KeyListener 
{ 
    static GameFrame gameFrame = new GameFrame(); 

    public int x = 350; 
    public int y = 250; 
    public int keyCode; 

    public static void main (String[] args) 
    { 
     JFrame frame = new JFrame ("Java Game"); 
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     frame.setSize (800, 600); 
     frame.setResizable (false); 
     frame.getContentPane().setBackground (Color.WHITE); 
     frame.getContentPane().add (gameFrame); 
     frame.addKeyListener (gameFrame); 
     frame.setVisible (true); 
    } 

    @Override 
    public void paintComponent (Graphics graphics) 
    { 
     super.paintComponent (graphics); 
     graphics.setColor (Color.BLACK); 
     graphics.fillRect (x, y, 100, 100); 
    } 

    public void keyPressed (KeyEvent event) 
    { 
     keyCode = event.getKeyCode(); 

     new Timer (100, new ActionListener() 
     { 
      public void actionPerformed (ActionEvent event) 
      { 
       if (keyCode == KeyEvent.VK_LEFT) 
       { 
        x--; 
        repaint(); 
       } 
       if (keyCode == KeyEvent.VK_RIGHT) 
       { 
        x++; 
        repaint(); 
       } 
       if (keyCode == KeyEvent.VK_UP) 
       { 
        y--; 
        repaint(); 
       } 
       if (keyCode == KeyEvent.VK_DOWN) 
       { 
        y++; 
        repaint(); 
       } 
      } 
     }).start(); 
    } 

    public void keyReleased (KeyEvent event) {} 
    public void keyTyped (KeyEvent event) {} 
} 
+0

你的'keyReleased()'方法中没有任何东西。 – 2015-02-10 03:12:38

+0

@ PM77-1我知道。我在我的问题中说过。我还说过,我不知道应该在我的'keyReleased()'方法中放置什么。 – AmiableNebula 2015-02-10 03:13:49

+2

你的'keyReleased'方法需要停止计时器。另外,你的'keyPressed'方法如果它已经在运行,就不需要启动定时器。为了对定时器做些什么,你需要一个引用它 - 这应该可能存储在一个字段中。 – immibis 2015-02-10 03:15:17

回答

1
  • 避免KeyListener,严重的是,他们更麻烦比他们的价值,使用的键绑定API来代替。 How to Use Key Bindings

有很多方法可以实现这一点。更好的方法之一是使用间接方法。也就是说,用户按下一个键,并且您提出一个标志来指示哪个按下了,他们释放了这个键,您重置了这个标志,表明这个键不再被按下。

然后,您使用某种更新循环来更改基于哪些键当前处于活动状态的对象的位置。

但是为什么要这么麻烦我听到你问。当用户按下一个按键时,它们在第一次按键和重复按键通知之间是短暂的延迟(当按键关闭时,操作系统会发送按键事件直到它被释放),这使得机芯看起来有点“交错”。

相反,我们升旗和使用不断更新循环来更改基于该标志的状态,从而平抑的关键事件,例如对象的状态...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test{ 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class TestPane extends JPanel { 

     public enum HorizontalMovement { 
      NONE, 
      LEFT, 
      RIGHT 
     } 

     private HorizontalMovement horizontalMovement = HorizontalMovement.NONE; 

     private int xPos = 0; 

     public TestPane() { 
      addKeyPressedBinding("left.pressed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.LEFT)); 
      addKeyPressedBinding("right.pressed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.RIGHT)); 
      addKeyReleasedBinding("left.relesed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.NONE)); 
      addKeyReleasedBinding("right.relesed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.NONE)); 

      Timer timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        switch (horizontalMovement) { 
         case LEFT: 
          xPos--; 
          break; 
         case RIGHT: 
          xPos++; 
          break; 
        } 
        if (xPos < 0) { 
         xPos = 0; 
        } else if (xPos + 50 > getWidth()) { 
         xPos = getWidth() - 50; 
        } 
        repaint(); 
       } 
      }); 
      timer.start(); 

     } 

     protected void addKeyPressedBinding(String name, int keyCode, Action action) { 
      KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, false); 
      addKeyBinding(name, ks, action); 
     } 

     protected void addKeyReleasedBinding(String name, int keyCode, Action action) { 
      KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, true); 
      addKeyBinding(name, ks, action); 
     } 

     protected void addKeyBinding(String name, KeyStroke ks, Action action) { 
      InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap am = getActionMap(); 

      im.put(ks, name); 
      am.put(name, action); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      Rectangle box = new Rectangle(xPos, (getHeight() - 50)/2, 50, 50); 
      g2d.setColor(Color.BLUE); 
      g2d.fill(box); 
      g2d.dispose(); 
     } 

     protected void addKeyBinding(String left, int VK_LEFT, MoveHorizontialAction moveHorizontialAction) { 
      throw new UnsupportedOperationException("Not supported yet."); 
     } 

     protected class MoveHorizontialAction extends AbstractAction { 

      private HorizontalMovement movement; 

      public MoveHorizontialAction(HorizontalMovement movement) { 
       this.movement = movement; 
      } 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       horizontalMovement = movement; 
      } 

     } 

    } 

} 
相关问题