S-JIS[2009-03-29/2009-03-31] 変更履歴

キーアクション(Swing)

Swingでキー押下時に何らかの処理をするには、InputMapとActionMapを利用する。


JTableで行追加・削除する例

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

Swing目次へ戻る / Java目次へ戻る
メールの送信先:ひしだま