Swingでキー押下時に何らかの処理をするには、InputMapとActionMapを利用する。
|
|
JTableでInsertキーを押した時にレコードを追加し、Deleteキーを押した時にレコードを削除する例。
import java.awt.event.KeyEvent; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.KeyStroke;
class MyTable extends JTable { public MyTable() { setKeyAction( // INSERTキー KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), new AddAction()); setKeyAction( // SHIFT+INSERTキー KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.SHIFT_DOWN_MASK), new AddAction()); setKeyAction( // DELETEキー KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), new DelAction()); } protected void setKeyAction(KeyStroke key, Action a) { //Object name = a.getValue(Action.NAME); //↑Actionのコンストラクターで指定した名前 Object name = a; InputMap im; im = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); im.put(key, name); im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); im.put(key, name); // im = getInputMap(JComponent.WHEN_FOCUSED); // im.put(key, name); ActionMap am = getActionMap(); am.put(name, a); } }
Actionに名前を付けておき、InputMapにはキーの種類とその名前を登録する。
別々のキーに同じ名前を登録しておけば、同じアクションを呼び出せる。
ActionMapには、InputMapに登録した名前に対し、実際に呼ばれるアクションを登録する。
なお、名前のオブジェクト(クラス)は何でも良いようだが、基本的にはActionインスタンスそのものを使うようだ。[/2009-03-30]
getInputMap()の引数には、どういう状態(フォーカスの有無)でキー押下イベントを取得するかが指定できる。
例えばWHEN_FOCUSだと、コンポーネントにフォーカスが当たっている場合のキー入力となる。
これらの(InputMapやActionMapへの)登録は、registerKeyboardAction()を呼べば自動的にやってくれる。[2009-03-30]
(が、それは古いメソッドらしい…[2009-03-31])
import java.awt.event.ActionEvent; import javax.swing.AbstractAction;
/** JTableに行を追加するアクション */ public class AddAction extends AbstractAction { public AddAction() { super("table-row-add"); } @Override public void actionPerformed(ActionEvent e) { JTable table = (JTable) e.getSource(); int r = table.getSelectedRow(); int s = r; if (r >= 0) { // 行が選択されているとき if ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) { // SHIFTキーが押されているとき、選択行の上に新規行を挿入 s++; } else { // SHIFTキーが押されていないとき、選択行の下に新規行を挿入 r++; } } else { // 選択されていないとき if ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) { // SHIFTキーが押されているとき、最も上の行に新規行を挿入 r = 0; } else { // SHIFTキーが押されていないとき、最も下の行に新規行を追加 r = table.getRowCount(); } } DefaultTableModel model = (DefaultTableModel) table.getModel(); model.insertRow(r, new Object[] {}); //空行追加 table.getSelectionModel().setSelectionInterval(s, s); //選択し直す } }
/** JTableから行を削除するアクション */ public class DelAction extends AbstractAction { public DelAction() { super("table-row-del"); } @Override public void actionPerformed(ActionEvent e) { JTable table = (JTable) e.getSource(); DefaultTableModel model = (DefaultTableModel) table.getModel(); // 選択されている行を削除 int[] rs = table.getSelectedRows(); for (int i = 0; i < rs.length; i++) { rs[i] = table.convertRowIndexToModel(rs[i]); } Arrays.sort(rs); for (int i = rs.length - 1; i >= 0; i--) { model.removeRow(rs[i]); } } }
上記のInputMapやActionMapへの登録を行うメソッドがJComponentには用意されている。[2009-03-30]
(ただし、これは古いメソッドらしい…InputMapやActionMapに直接アクセスする方が新しいらしい。[2009-03-31])
protected void setKeyAction(KeyStroke key, Action a) { registerKeyboardAction(a, key, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); registerKeyboardAction(a, key, JComponent.WHEN_IN_FOCUSED_WINDOW); // registerKeyboardAction(a, key, JComponent.WHEN_FOCUSED); }
登録されているキーの一覧は、以下のようにして確認できる。
System.out.println(Arrays.toString(super.getRegisteredKeyStrokes()));