javax.swing.JRadioButton 是單選按鈕組件,配合 ButtonGroup 實現「單選互斥」邏輯:同一組內同一時刻僅有一個按鈕被選中。本文通過完整示例講解創建、分組、事件監聽、佈局管理等核心用法。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class RadioButtonDemo extends JFrame implements ActionListener {
private JTextField displayField;
private ButtonGroup group;
public RadioButtonDemo() {
setTitle("JRadioButton 單選按鈕示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout(FlowLayout.CENTER, 20, 20));
setSize(400, 200);
setLocationRelativeTo(null); // 居中顯示
// 1. 創建單選按鈕
JRadioButton rbA = new JRadioButton("選項 A");
JRadioButton rbB = new JRadioButton("選項 B");
JRadioButton rbC = new JRadioButton("選項 C");
// 2. 添加動作監聽器 (本類實現 ActionListener)
rbA.addActionListener(this);
rbB.addActionListener(this);
rbC.addActionListener(this);
// 3. 關鍵: 加入 ButtonGroup 實現互斥
group = new ButtonGroup();
group.add(rbA);
group.add(rbB);
group.add(rbC);
// 4. 可選: 設置默認選中
rbA.setSelected(true);
// 5. 顯示選中結果的文本框
displayField = new JTextField(15);
displayField.setEditable(false);
displayField.setText("當前選中: A");
// 6. 添加到容器
add(rbA);
add(rbB);
add(rbC);
add(new JLabel("選中值:"));
add(displayField);
}
@Override
public void actionPerformed(ActionEvent e) {
// 獲取觸發事件的按鈕文本 (即 ActionCommand,默認為按鈕文本)
String selected = e.getActionCommand();
displayField.setText("當前選中: " + selected);
}
public static void main(String[] args) {
// 確保在 EDT (事件分發線程) 中創建 GUI
SwingUtilities.invokeLater(() -> {
new RadioButtonDemo().setVisible(true);
});
}
}
| 類/方法 | 作用 | 注意事項 |
|---|---|---|
ButtonGroup | 邏輯分組,不負責佈局 | 不繼承 Component,不可直接加入容器;僅管理選中狀態互斥 |
group.add(btn) | 將按鈕加入分組 | 一個按鈕只能屬於一個群組 |
group.getSelection() | 獲取當前選中的 ButtonModel | 無選中時返回 null |
group.clearSelection() | 取消所有選中 | 視覺上所有按鈕恢復未選狀態 |
setActionCommand(str) | 設置事件命令字串 | 默認使用按鈕文本;建議顯式設置區分業務標識 |
setSelected(true) | 程式化選中 | 會觸發 ActionEvent (若已註冊監聽器) |
JRadioButton rbVip = new JRadioButton("VIP 用戶");
rbVip.setActionCommand("USER_TYPE_VIP"); // 業務代碼而非顯示文本
JRadioButton rbNormal = new JRadioButton("普通用戶");
rbNormal.setActionCommand("USER_TYPE_NORMAL");
rbVip.addActionListener(e -> {
String type = e.getActionCommand(); // 直接拿業務代碼
userService.updateType(currentUserId, type);
});
// 例如提交表單時讀取
ButtonModel selectedModel = group.getSelection();
if (selectedModel != null) {
String cmd = selectedModel.getActionCommand();
// 處理業務...
} else {
JOptionPane.showMessageDialog(this, "請選擇一個選項");
}
// 垂直排列
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
// 支援 HTML 富文本 (換行、粗體、顏色)
JRadioButton rbHtml = new JRadioButton("重要
選項(必選)");
UIManager.put("RadioButton.icon", new ImageIcon("custom_radio_off.png"));
UIManager.put("RadioButton.select", new ImageIcon("custom_radio_on.png"));
// 必須在創建組件前設置,或調用 SwingUtilities.updateComponentTreeUI(frame)
| 現象 | 原因 | 解決 |
|---|---|---|
| 多個按鈕可同時選中 | 未加入同一 ButtonGroup | 確保所有互斥按鈕 group.add() |
| 事件觸發兩次 | 選中/取消選中各觸發一次 | 在 listener 中判斷 btn.isSelected() 只處理選中 |
| 圖標與文本重疊/間距異常 | 默認圖標大小固定 | 用 setIconTextGap(int) 調整間距 |
| 鍵盤無法切換選項 | 焦點遍歷策略問題 | 確保按鈕 setFocusable(true) 且在同一焦點循環 |
JRadioButton + ButtonGroup 是 Swing 實現單選交互的標準組合。掌握 分組管理、ActionCommand 業務解耦、EDT 線程安全、動態狀態讀取 四大核心點,即可應對絕大多數表單單選場景。現代 Java 桌面開發亦可考慮 JavaFX (RadioButton + ToggleGroup) 獲得更豐富的樣式與綁定能力。