Swing/AutoWrapTableCell のバックアップの現在との差分(No.4)
TITLE:JTableのセルの高さを自動調整
Posted by terai at 2010-10-25
JTableのセルの高さを自動調整
JTableのセルの高さを、文字列の折り返しに応じて自動調整します。-
category: swing
folder: AutoWrapTableCell
title: JTableのセルの高さを自動調整
tags: [JTable, JTextArea, TableCellRenderer]
author: aterai
pubdate: 2010-10-25T14:24:03+09:00
description: JTableのセルの高さを、文字列の折り返しに応じて自動調整します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2017/06/automatically-adjust-height-of-jtables.html lang: en
概要
JTable
のセルの高さを、文字列の折り返しに応じて自動調整します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
#screenshot
サンプルコード
#spanend
#spanadd
class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
#spanend
private final List<List<Integer>> cellHeights = new ArrayList<>();
#spandel
**サンプルコード [#f1f7d94f]
#spanend
#spandel
#code{{
#spanend
#spandel
JTable table = new JTable(model) {
#spanend
@Override public void doLayout() {
initPreferredHeight();
super.doLayout();
@Override public void updateUI() {
super.updateUI();
setLineWrap(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
setName("Table.cellRenderer");
}
@Override public void columnMarginChanged(ChangeEvent e) {
initPreferredHeight();
super.columnMarginChanged(e);
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
setFont(table.getFont());
setText(Objects.toString(value, ""));
adjustRowHeight(table, row, column);
return this;
}
private void initPreferredHeight() {
int vc = convertColumnIndexToView(AUTOWRAP_COLUMN);
TableColumn col = getColumnModel().getColumn(vc);
for(int row=0; row<getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, vc);
if(c instanceof JTextArea) {
JTextArea a = (JTextArea)c;
int h = getPreferredHeight(a); // + getIntercellSpacing().height;
//if(getRowHeight(row)!=h)
setRowHeight(row, h);
}
#spanadd
#spanend
/**
* Calculate the new preferred height for a given row,
* and sets the height on the table.
* http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx
*/
private void adjustRowHeight(JTable table, int row, int column) {
// The trick to get this to work properly is to set the width of the column to
// the textarea. The reason for this is that getPreferredSize(), without a width
// tries to place all the text in one line.
// By setting the size with the width of the column,
// getPreferredSize() returnes the proper height which the row should have in
// order to make room for the text.
// int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth();
// int cWidth = table.getCellRect(row, column, false).width; // IntercellSpacingを無視
// setSize(new Dimension(cWidth, 1000));
#spanadd
#spanend
setBounds(table.getCellRect(row, column, false)); // setSizeではなくsetBoundsでも可
// doLayout(); // 必要なさそう
#spanadd
#spanend
int preferredHeight = getPreferredSize().height;
while (cellHeights.size() <= row) {
cellHeights.add(new ArrayList<>(column));
}
List<Integer> list = cellHeights.get(row);
while (list.size() <= column) {
list.add(0);
}
list.set(column, preferredHeight);
int max = list.stream().max(Integer::compare).get();
if (table.getRowHeight(row) != max) {
table.setRowHeight(row, max);
}
}
//http://tips4java.wordpress.com/2008/10/26/text-utilities/
private int getPreferredHeight(JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
#spandel
};
#spanend
#spanadd
}
#spanend
View in GitHub: Java, Kotlin解説
上記のサンプルでは、セルレンダラーに、setLineWrap(true)としたJTextAreaを使用し、カラムサイズの変更などがあったときに、そのJTextAreaの高さを取得してJTable#setRowHeight(int)メソッドで各行の高さとして設定しています。解説
上記のサンプルでは、セルレンダラーにsetLineWrap(true)
を指定したJTextArea
を使用し、カラムサイズの変更が実行されるたびにそのJTextArea
の高さを取得してJTable#setRowHeight(int)
メソッドで各行の高さを更新しています。
参考リンク
- Text Utilities « Java Tips Weblog
- JTableのセル幅で文字列を折り返し
- -
- 上記の
TextAreaCellRenderer
を複数インスタンス生成して一つのJTable
に設定すると正常に折り返しできなくなる- セルの高さをキャッシュしている
cellHeights
をstatic
にすれば解決するが、その場合複数のJTable
に適用すると正常に動作しない#spanend #spanadd // NG #spanend #spanadd table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer()); #spanend #spanadd table.getColumnModel().getColumn(1).setCellRenderer(new TextAreaCellRenderer()); #spanend #spandel **コメント [#y52d6f46] #spanend - 高さが微妙に更新されない場合がある…。 -- [[terai]] &new{2010-10-27 (水) 14:02:02}; - フレームのサイズ(JTableの高さ)を微妙に調整すると、スクロールバーが表示・非表示を繰り返す場合がある。 -- [[terai]] &new{2010-11-02 (火) 20:23:55}; - 上二つの原因は同じだと思うけど、今のところ何が問題なのか分からず、お手上げ状態です。 -- [[terai]] &new{2010-11-02 (火) 20:26:21}; #spanadd // OK #spanend #spanadd TableCellRenderer renderer = new TextAreaCellRenderer(); #spanend #spanadd table.getColumnModel().getColumn(0).setCellRenderer(renderer); #spanend #spanadd table.getColumnModel().getColumn(1).setCellRenderer(renderer); #spanend #spanadd
- セルの高さをキャッシュしている
参考リンク
- JTable multiline cell renderer
- Text Utilities « Java Tips Weblog
- JTableのセル幅で文字列を折り返し
- ToolkitからScreenResolutionを取得し、コンポーネントで使用するフォントの倍率を変更する
-
JTable
の行の高さはLookAndFeel
依存で一定のため、フォントサイズの変更に応じた自動調整などは行われない(自前で高さを変更する必要がある)
-