S-JIS[2009-04-05] 変更履歴

JRadioButton(Swing)

ラジオボタン(固定された選択肢の中から1つを選ぶ)はSwingではJRadioButtonクラスを使う。
1つのラジオボタンにつき1つのJRadioButtonインスタンスを用意し、選択肢としてのグルーピングはButtonGroupに登録することで管理される。


サンプル

import javax.swing.ButtonGroup;
import javax.swing.JRadioButton;
	/**
	 * ラジオボタン・グループの初期化
	 */
	private void initPane(Container c) {
		JRadioButton r1 = new JRadioButton("選択肢1");
		JRadioButton r2 = new JRadioButton("選択肢2");
		JRadioButton r3 = new JRadioButton("選択肢3");

		// ボタングループへの登録
		ButtonGroup bg = new ButtonGroup();
		bg.add(r1);
		bg.add(r2);
		bg.add(r3);

		// ラジオボタンの表示
		c.setLayout(new FlowLayout());
		c.add(r1);
		c.add(r2);
		c.add(r3);
	}

ButtonGroup自体はJComponent等のコンポーネントではないので、表示したりするものではない。


カーソルキーでの選択移動

デフォルトでは、マウスで選択肢をクリックした場合やスペースキーを押した場合に選択されている選択肢が移動する。
他のアプリではカーソルキーを押すことで選択肢が移動できるものがあるが、その動作を行うには独自実装する必要がある。

各ラジオボタンのキーイベントでカーソルキーの押下を捕捉し、新しいラジオボタンを選択状態に変えればよい。
グループに所属しているラジオボタンの一覧はボタングループが保持しているので、新しいラジオボタンを探すのはそちらでないと出来ない。
選択状態に変えるにはボタンのsetSelected(true)を呼べばよい。(これで、以前の選択肢は選択解除される。)
ただし、これだけではフォーカスは移らないので、別途フォーカスも移しておかないと変になる。

class MyButtonGroup extends ButtonGroup implements KeyListener {

	@Override
	public void add(AbstractButton b) {
		super.add(b);
		b.removeKeyListener(this);
		b.addKeyListener(this);
	}

	@Override
	public void remove(AbstractButton b) {
		b.removeKeyListener(this);
		super.remove(b);
	}
	@Override
	public void keyPressed(KeyEvent e) {
		int size = buttons.size();	//グループに登録されているボタンの個数
		if (size <= 0) {
			return;
		}

		int z;
		switch (e.getKeyCode()) {
		case KeyEvent.VK_UP:   case KeyEvent.VK_LEFT:
			z = size - 1;
			break;
		case KeyEvent.VK_DOWN: case KeyEvent.VK_RIGHT:
			z = +1;
			break;
		default:
			return;
		}

		AbstractButton b = (AbstractButton) e.getSource();	//カーソルキーが押された際にフォーカスのあったラジオボタン
		for (int i = 0; i < size; i++) {
			if (buttons.get(i) == b) {
				int n = (i + z) % size;
				AbstractButton nb = buttons.get(n);	//新しいラジオボタン

				nb.setSelected(true);		//選択状態に変える
				nb.requestFocusInWindow();	//フォーカスを移す

				e.consume();
				return;
			}
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}

	@Override
	public void keyTyped(KeyEvent e) {
	}
}

ExButtonGroup

上記のロジックは、インデックスの増分を変数zで保持している。
マイナス方向の場合、単純に-1とすると、「加算したインデックスが負の数になった場合の処理」を別途入れる必要が出てくる。
そこで増分を「size - 1」にして、新しいインデックスは「増分加算後にsizeで割った余り」にすると、特別なロジックは不要になる。
例えばインデックスが1だったら「(1 + size - 1) % size」で余りは0、インデックスが0だったら「(0 + size - 1) % size」で余りはsize-1となる。
増分が+1でも全く同じ計算式で問題ない。
これはMSX-BASIC時代の定番アルゴリズム(方角(上が0で右上が1、右が2、…、左上が7)を1ずつずらす)そのもの。


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