[Java] 利用 getInputMap、getActionMap 和 KeyStroke 從外部新增 Action
承自上一篇 javax 中 KeyListener 的遲鈍問題 解決了聽取按鍵的延遲問題,終於看懂那個 StackOverflow 的解答,試著自己把他做出來,而且更貪心地我想做成一個類別,之後都能用,就像 pygame 裡 sprite 的 update() 一樣。但是 Java 寫起來超級長而且很不自由,非常不滿意,期待之後能改良:
首先這個類別 GameObject 是繼承自 JLabel ,他是 JComponent 的子類別就有 InputMap 和 ActionMap 可以使用鍵盤功能,簡單型式(不考慮聽取鍵盤的延遲問題的話的作法)如下:
GameObject.java
package game; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JLabel; import javax.swing.KeyStroke; public class GameObject extends JLabel implements ActionListener{ Action goLeft; // 宣告一個 Action 準備給按下左鍵時動作,內容在下面重載 public GameObject() { goLeft = new LeftAction(); this.getInputMap().put(KeyStroke.getKeyStroke("pressed LEFT"), "leftAct"); this.getActionMap().put("leftAct", goLeft); // 用 "pressed Left" 字串會得到一個鍵值,並對應到 "leftAct" 字串 // 再用 ActionMap 將 "leftAct" 對應到動作 goLeft,這是一個 AbstractAction 抽象物件 } public class LeftAction extends AbstractAction { @Override // 在此只能做 println ,沒辦法 public void actionPerformed(ActionEvent e) { // 控制 GameObject 的位置 System.out.println("Go leftward"); // 此處用 this 會是指 LeftAction } }; @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub }; }
MyFrame.java
package game; import java.awt.Color; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; public class MyFrame extends JFrame{ GameObject myLabel; JPanel myPanel; MyFrame(){ myLabel = new GameObject(); myLabel.setSize(80,60); myLabel.setBackground(Color.green); myLabel.setOpaque(true); myLabel.setLocation(100,400); // 如同 GameObject.java內的寫法,這次從外部來使用 // 補上 InputMap ActionMap 還有要動作的內容直接 new myLabel.getInputMap().put(KeyStroke.getKeyStroke("pressed RIGHT"), "rightAct"); myLabel.getActionMap().put("rightAct", new AbstractAction() { @Override // 按下右鍵時會動作,將 myLabel 向右移動 2px public void actionPerformed(ActionEvent e) { myLabel.setLocation(myLabel.getX() + 2, myLabel.getY()); } }); myPanel = new JPanel(); myPanel.setLayout(null); myPanel.add(myLabel); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(500,600); this.add(myPanel); this.setVisible(true); } }
Main.java
package game; public class Main { public static void main(String[] args) { new MyFrame(); } }
以上會得到一個 JFrame 裡的 JLabel,按鍵盤左鍵將在 console 印出 "Go leftward",而按鍵盤右鍵會直接將 JLabel 方塊向右移動,兩者可以做一個比較。
這個作法非常單純,缺點是按一個鍵為一個動作,如果把向右和向上的動作做出來,也沒辦法兩個一起按就往右上移動,要統合的話要將這些按鍵放入一個 List 並打開 timer 來考慮
留言
張貼留言