ラジオボタン(固定された選択肢の中から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) {
}
}
上記のロジックは、インデックスの増分を変数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ずつずらす)そのもの。