[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 來考慮
留言
張貼留言