JTable은 JComponent 클래스의 하위 클래스로, 여러 행(row)과 열(column)에 정보를 표시하는 테이블을 만들 때 사용됩니다. JTable에서 값이 선택되면 TableModelEvent가 발생하며, 이 이벤트는 TableModelListener 인터페이스를 구현하여 처리할 수 있습니다.
JTable 셀에 라디오 버튼(JRadioButton)을 추가하거나 삽입하려면 TableCellRenderer 인터페이스와 DefaultCellEditor 클래스를 커스터마이징해야 합니다. 렌더러(Renderer)는 셀에 라디오 버튼을 화면에 표시하는 역할을 담당하고, 에디터(Editor)는 사용자가 해당 셀을 클릭했을 때 라디오 버튼과 상호작용할 수 있도록 해줍니다. 또한 여러 라디오 버튼 중 하나만 선택되도록 하려면 ButtonGroup으로 버튼들을 묶어주는 것이 좋습니다.
예제 코드
아래 예제는 과목(Course)별 기술(Technology) 항목을 보여주는 JTable의 두 번째 열에 라디오 버튼을 배치하고, ButtonGroup을 통해 하나의 옵션만 선택 가능하도록 구현한 코드입니다.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class JTableRadioButtonTest extends JFrame {
private DefaultTableModel dtm;
private ButtonGroup bg;
private JTable table;
private JScrollPane jsp;
public JTableRadioButtonTest() {
setTitle("JTableRadioButton Test");
dtm = new DefaultTableModel();
dtm.setDataVector(new Object[][] {
{"Course 1", new JRadioButton("Java")},
{"Course 1", new JRadioButton("Python")},
{"Course 1", new JRadioButton("Scala")},
{"Course 2", new JRadioButton("Selenium")},
{"Course 2", new JRadioButton("Java Script")}
}, new Object[] {"Course", "Technology"});
table = new JTable(dtm) {
public void tableChanged(TableModelEvent tme) {
super.tableChanged(tme);
repaint();
}
};
bg = new ButtonGroup();
bg.add((JRadioButton) dtm.getValueAt(0, 1));
bg.add((JRadioButton) dtm.getValueAt(1, 1));
bg.add((JRadioButton) dtm.getValueAt(2, 1));
bg.add((JRadioButton) dtm.getValueAt(3, 1));
bg.add((JRadioButton) dtm.getValueAt(4, 1));
table.getColumn("Technology").setCellRenderer(new RadioButtonRenderer());
table.getColumn("Technology").setCellEditor(new RadioButtonEditor(new JCheckBox()));
jsp = new JScrollPane(table);
add(jsp, BorderLayout.NORTH);
setSize(400, 275);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new JTableRadioButtonTest();
}
}
class RadioButtonRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) return null;
return (Component) value;
}
}
class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
private JRadioButton button;
public RadioButtonEditor(JCheckBox checkBox) {
super(checkBox);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value == null) return null;
button = (JRadioButton) value;
button.addItemListener(this);
return (Component) value;
}
public Object getCellEditorValue() {
button.removeItemListener(this);
return button;
}
public void itemStateChanged(ItemEvent e) {
super.fireEditingStopped();
}
}코드 설명
1. 데이터 모델 설정
DefaultTableModel의 setDataVector() 메서드를 사용하여 각 행의 두 번째 열에 JRadioButton 객체를 직접 저장합니다. 첫 번째 열에는 과목명, 두 번째 열에는 기술명을 라벨로 가진 라디오 버튼이 들어갑니다.
2. 라디오 버튼 그룹화
ButtonGroup에 모든 라디오 버튼을 추가하면 그룹 내에서 한 번에 하나의 버튼만 선택할 수 있습니다. 이는 일반적인 라디오 버튼의 동작 방식과 동일합니다.
3. 렌더러(RadioButtonRenderer)
TableCellRenderer를 구현한 RadioButtonRenderer는 셀 값이 JRadioButton이면 해당 컴포넌트를 그대로 반환하여 화면에 라디오 버튼이 표시되도록 합니다.
4. 에디터(RadioButtonEditor)
DefaultCellEditor를 상속받고 ItemListener를 구현한 RadioButtonEditor는 사용자가 셀을 편집할 때 실제 JRadioButton을 반환합니다. 아이템 상태가 변경되면 fireEditingStopped()를 호출하여 편집을 종료하고 변경 사항을 반영합니다.
실행 결과
프로그램을 실행하면 다음과 같이 "Course" 열과 "Technology" 열로 구성된 테이블이 표시되며, Technology 열의 각 셀에는 라디오 버튼이 나타납니다. 버튼을 클릭하면 해당 옵션이 선택되고, 다른 버튼을 선택하면 이전 선택이 자동으로 해제됩니다.
