2015-02-10 75 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; 
      } 

     } 

    } 

} 
相關問題