JTableHeader란 무엇인가?
JTableHeader는 JComponent 클래스를 상속하는 하위 클래스입니다.
- JTable 객체를 생성하면 생성자가 새로운 JTableHeader 객체를 자동으로 만들어 테이블 컴포넌트의 헤더를 관리합니다.
- JTableHeader 객체는 테이블의 컬럼 모델(column model)과 연결되어 있으며, 이를 통해 UI 위임 객체(UI delegate)가 컬럼을 드래그하거나 각 컬럼의 헤더 셀을 렌더링할 수 있습니다.
- JTable은 setTableHeader() 메서드로 테이블 헤더 컴포넌트의 JTableHeader 객체를 설정하고, getTableHeader() 메서드로 해당 객체에 대한 참조를 반환합니다.
JTable에서 단어 줄바꿈(word-wrap)이 적용된 테이블 헤더는 DefaultTableModel 또는 AbstractTableModel 클래스를 커스터마이징하여 구현할 수 있습니다. 핵심 원리는 컬럼 이름을 HTML 태그로 감싸 Swing이 헤더 텍스트를 여러 줄로 렌더링하도록 만드는 것입니다.
예제 코드
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class WordWrappingTableHeaderTest extends JFrame {
private JTable table;
public WordWrappingTableHeaderTest() {
setTitle("WordWrappingTableHeader Test");
DefaultTableColumnModel tableColumnModel = new DefaultTableColumnModel() {
@Override
public void addColumn(TableColumn column) {
column.setHeaderRenderer(new JTableHeader().getDefaultRenderer());
super.addColumn(column);
}
};
table = new JTable();
table.setFillsViewportHeight(true);
table.setColumnModel(tableColumnModel);
table.setModel(new DemoTableModel(Arrays.asList(
"Word Wrapping TableHeader Test",
"Word Wrapping TableHeader Test",
"Word Wrapping TableHeader Test"), 20));
add(new JScrollPane(table));
setSize(450, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
class DemoTableModel extends AbstractTableModel {
private ArrayList<String> wrappedColumnNames = new ArrayList<>();
private int numRows;
DemoTableModel(List<String> columnNames, int numRows) {
// 컬럼 이름을 <html> 태그로 감싸면 헤더에서 자동 줄바꿈이 적용됩니다.
for (String name : columnNames)
wrappedColumnNames.add("<html>" + name + "</html>");
this.numRows = numRows;
}
public int getRowCount() {
return numRows;
}
public int getColumnCount() {
return wrappedColumnNames.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
return Integer.valueOf(10000 + (rowIndex + 1) * (columnIndex + 1));
}
public String getColumnName(int column) {
return wrappedColumnNames.get(column);
}
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
}
public static void main(String[] args) {
new WordWrappingTableHeaderTest();
}
}
코드 핵심 포인트
- HTML 렌더링 활용: Swing의 기본 렌더러는 <html> 태그로 감싼 텍스트를 HTML로 해석합니다. 따라서 컬럼 이름을 <html>...</html>로 감싸면 헤더 셀의 너비에 맞춰 텍스트가 자동으로 줄바꿈됩니다.
- 헤더 렌더러 지정: DefaultTableColumnModel의 addColumn() 메서드를 오버라이드하여 각 컬럼에 JTableHeader의 기본 렌더러를 명시적으로 설정함으로써 HTML 렌더링이 정상적으로 동작하도록 합니다.
- 모델 커스터마이징: AbstractTableModel을 상속한 DemoTableModel에서 getColumnName() 메서드가 HTML 태그로 감싸진 컬럼 이름을 반환하도록 처리합니다.
실행 결과
프로그램을 실행하면 아래 그림과 같이 헤더 텍스트가 한 줄로 잘리지 않고 셀 너비에 맞게 여러 줄로 표시되는 것을 확인할 수 있습니다.
