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()));