Swing/ColumnSpanningCellRenderer のバックアップ(No.12)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/ColumnSpanningCellRenderer へ行く。
- 1 (2013-05-13 (月) 16:59:22)
- 2 (2013-06-04 (火) 13:37:19)
- 3 (2013-06-04 (火) 15:08:18)
- 4 (2013-06-04 (火) 18:25:04)
- 5 (2013-06-05 (水) 10:00:24)
- 6 (2013-08-17 (土) 01:31:41)
- 7 (2014-05-13 (火) 14:47:03)
- 8 (2014-10-26 (日) 04:03:20)
- 9 (2014-11-22 (土) 04:02:40)
- 10 (2015-03-01 (日) 16:07:55)
- 11 (2015-06-26 (金) 17:47:41)
- 12 (2016-01-13 (水) 13:38:38)
- 13 (2017-03-31 (金) 16:12:29)
- 14 (2017-04-07 (金) 13:51:51)
- 15 (2017-09-19 (火) 06:12:05)
- 16 (2018-02-24 (土) 19:45:40)
- 17 (2020-03-06 (金) 16:27:01)
- 18 (2021-08-19 (木) 00:54:24)
- 19 (2024-02-03 (土) 14:09:44)
- title: JTableのセルを横方向に連結する
tags: [JTable, TableCellRenderer, JTextArea, JScrollPane]
author: aterai
pubdate: 2013-05-13T16:59:22+09:00
description: JTableのセルを横方向に連結するセルレンダラーを作成します。
hreflang:
href: http://java-swing-tips.blogspot.com/2013/05/column-spanning-tablecellrenderer.html lang: en
概要
JTable
のセルを横方向に連結するセルレンダラーを作成します。
Screenshot
Advertisement
サンプルコード
class ColumnSpanningCellRenderer extends JPanel implements TableCellRenderer {
private final JTextArea textArea = new JTextArea(2, 999999);
private final JLabel label = new JLabel();
private final JLabel iconLabel = new JLabel();
private final JScrollPane scroll = new JScrollPane();
public ColumnSpanningCellRenderer() {
super(new BorderLayout(0, 0));
scroll.setViewportView(textArea);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setBorder(BorderFactory.createEmptyBorder());
scroll.setViewportBorder(BorderFactory.createEmptyBorder());
scroll.setOpaque(false);
scroll.getViewport().setOpaque(false);
textArea.setBorder(BorderFactory.createEmptyBorder());
textArea.setMargin(new Insets(0, 0, 0, 0));
textArea.setForeground(Color.RED);
textArea.setEditable(false);
textArea.setFocusable(false);
textArea.setOpaque(false);
iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
iconLabel.setOpaque(false);
Border b1 = BorderFactory.createEmptyBorder(2, 2, 2, 2);
Border b2 = BorderFactory.createMatteBorder(0, 0, 1, 1, Color.GRAY);
label.setBorder(BorderFactory.createCompoundBorder(b2, b1));
setBackground(textArea.getBackground());
setOpaque(true);
add(label, BorderLayout.NORTH);
add(scroll);
}
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Test test;
if (value instanceof Test) {
test = (Test) value;
add(iconLabel, BorderLayout.WEST);
} else {
int mrow = table.convertRowIndexToModel(row);
String title = value != null ? value.toString() : "";
Test t = (Test) table.getModel().getValueAt(mrow, 0);
String text = t != null ? t.text : "";
Icon icon = t != null ? t.icon : null;
test = new Test(title, icon, text);
remove(iconLabel);
}
label.setText(test.title);
textArea.setText(test.text);
iconLabel.setIcon(test.icon);
Rectangle cr = table.getCellRect(row, column, false);
if (column != 0) {
cr.x -= iconLabel.getPreferredSize().width;
}
scroll.getViewport().setViewPosition(cr.getLocation());
if (isSelected) {
setBackground(Color.ORANGE);
} else {
setBackground(Color.WHITE);
}
return this;
}
}
View in GitHub: Java, Kotlin解説
文字列を配置したJTextArea
を各カラムごとにJViewport
で表示する領域を切り取ってセルに貼り付けています。さらに、JTable
のセルの縦罫線自体は、table.setShowVerticalLines(false);
などで非表示にすることでレンダラー内のJTextArea
は、連続しているように見せかけ、上部のJLabel
はBorder
を設定することで区切りを表示しています。
- メモ
- 列の入れ替えには対応していない
0
行目だけカラムヘッダのサイズを変更すると、描画がおかしくなる?0
行目ではなく、一番上に表示されている行の表示が乱れているJTextArea#scrollRectToVisible(...)
ではなく、JViewport#setViewPosition(Point)
を使用すると正常にリサイズできる0
行目だけ高さ1
のダミー行を追加して回避(ソートなどで問題が残る)
JTable
のクリック(セル選択?)などで表示が乱れる場合があるJTable#repaint(Rectangle)
をオーバーライドして常に全体を描画することで回避