TITLE:JTableのセルの高さを自動調整

Posted by at 2010-10-25

JTableのセルの高さを自動調整

JTableのセルの高さを、文字列の折り返しに応じて自動調整します。

AutoWrapTableCell.png

サンプルコード

JTable table = new JTable(model) {
  @Override public void doLayout() {
    initPreferredHeight();
    super.doLayout();
  }
  @Override public void columnMarginChanged(ChangeEvent e) {
    initPreferredHeight();
    super.columnMarginChanged(e);
  }
  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);
      }
    }
  }
  //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;
  }
};
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、セルレンダラーに、setLineWrap(true)としたJTextAreaを使用し、カラムサイズの変更などがあったときに、そのJTextAreaの高さを取得してJTable#setRowHeight(int)メソッドで各行の高さとして設定しています。

参考リンク

コメント

  • 高さが微妙に更新されない場合がある…。 -- aterai
  • フレームのサイズ(JTableの高さ)を微妙に調整すると、スクロールバーが表示・非表示を繰り返す場合がある。 -- aterai
  • 上二つの原因は同じだと思うけど、今のところ何が問題なのか分からず、お手上げ状態です。 -- aterai
  • レンダラーに以下のようなコードを追加して調整するサンプルを発見: JTable multiline cell renderer -- aterai
private ArrayList<ArrayList<Integer>> rowColHeight = new ArrayList<ArrayList<Integer>>();
private void adjustRowHeight(JTable table, int row, int column) {
  //int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth();
  int cWidth = table.getCellRect(row, column, false).width; //セルの内余白は含めない
  //setSize(new Dimension(cWidth, 1000)); //注目
  setBounds(table.getCellRect(row, column, false)); //もしくは?
  //doLayout();

  int prefH = getPreferredSize().height;
  while(rowColHeight.size() <= row) {
    rowColHeight.add(new ArrayList<Integer>(column));
  }
  ArrayList<Integer> colHeights = rowColHeight.get(row);
  while(colHeights.size() <= column) {
    colHeights.add(0);
  }
  colHeights.set(column, prefH);
  int maxH = prefH;
  for(Integer colHeight : colHeights) {
    if(colHeight > maxH) {
      maxH = colHeight;
    }
  }
  if(table.getRowHeight(row) != maxH) {
    table.setRowHeight(row, maxH);
  }
}
  • この方法だと、セルを描画する毎に、行の高さを調整するようになるので、これまでのドラッグでリサイズ中の微妙なサイズは無くなるはず(多少重くなるかもしれないけど、違いは全く感じられない)。 -- aterai