JTableで同一内容のセルを空表示にしてグループ化を表現する
Total: 3925
, Today: 1
, Yesterday: 2
Posted by aterai at
Last-modified:
概要
JTable
で直上のセルと同一内容のセルを空表示にして、行のグループ化を表現します。
Screenshot
Advertisement
サンプルコード
String colors = "colors";
String sports = "sports";
String food = "food";
addRowData(model, new RowData(colors, "blue", 1));
addRowData(model, new RowData(colors, "violet", 2));
addRowData(model, new RowData(colors, "red", 3));
addRowData(model, new RowData(colors, "yellow", 4));
addRowData(model, new RowData(sports, "baseball", 23));
addRowData(model, new RowData(sports, "soccer", 22));
addRowData(model, new RowData(sports, "football", 21));
addRowData(model, new RowData(sports, "hockey", 20));
addRowData(model, new RowData(food, "hot dogs", 10));
addRowData(model, new RowData(food, "pizza", 11));
addRowData(model, new RowData(food, "ravioli", 12));
addRowData(model, new RowData(food, "bananas", 13));
// ...
class RowDataRenderer implements TableCellRenderer {
private final TableCellRenderer renderer = new DefaultTableCellRenderer();
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel label = (JLabel) renderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
label.setHorizontalAlignment(SwingConstants.LEFT);
RowData data = (RowData) value;
switch (table.convertColumnIndexToModel(column)) {
case 0:
String str = data.getGroup();
if (row > 0) {
RowData prev = (RowData) table.getValueAt(row - 1, column);
if (Objects.equals(prev.getGroup(), str)) {
label.setText(" ");
break;
}
}
label.setText("+ " + str);
break;
case 1:
label.setText(data.getName());
break;
case 2:
label.setHorizontalAlignment(SwingConstants.RIGHT);
label.setText(Integer.toString(data.getCount()));
break;
default:
break;
}
return label;
}
}
View in GitHub: Java, Kotlin解説
TableModel
- データとしてすべての列に
RowData
のインスタンスのコピーを設定 - セルレンダラーで第
0
列目にRowData.getGroup()
の値、第1
列目にRowData.getName()
の値、第2
列目にRowData.getCount()
の値を表示するよう設定
- データとしてすべての列に
RowDataRenderer
JTable
の第0
列目で表示上の直上のセルとRowData.getGroup()
で取得した値が同一の場合、その値ではなく空白文字を表示するよう設定- 表示上の
0
行目には直上セルは存在しないので、常にそのままRowData.getGroup()
の値を表示する
- 表示上の
TableRowSorter
- ソートでグループ化が変化しないようにグループ化しない第
1
列目と第2
列目は、まず第0
列目をソートしてからその列の比較を行う以下のようなComparator
を使用するTableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel()); Comparator<RowData> c = Comparator.comparing(RowData::getGroup); sorter.setComparator(0, c); sorter.setComparator(1, c.thenComparing(RowData::getName)); sorter.setComparator(2, c.thenComparing(RowData::getCount)); table.setRowSorter(sorter);
- ソートでグループ化が変化しないようにグループ化しない第
参考リンク
- java - Swing - sort a JTable's rows but keep them grouped by one column and only show the value once on top of each group - Stack Overflow
- JTableでファイルとディレクトリを別々にソート