• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:TableColumnの幅を比率で設定
#navi(../)
*TableColumnの幅を比率で設定 [#s3d330d1]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2005-11-28~
更新日:&lastmod;
---
category: swing
folder: HeaderRatio
title: TableColumnの幅を比率で設定
tags: [JTable, JTableHeader, TableColumn, JScrollPane]
author: aterai
pubdate: 2005-11-28T18:26:47+09:00
description: 列幅調整がデフォルトのJTableで、ヘッダの各TableColumnが指定した比率の幅になるように設定します。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TSs6oj80RcI/AAAAAAAAAxs/hm2gp4ELiDI/s800/HeaderRatio.png
---
* 概要 [#summary]
列幅調整がデフォルトの`JTable`で、ヘッダの各`TableColumn`が指定した比率の幅になるように設定します。

#contents
#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TSs6oj80RcI/AAAAAAAAAxs/hm2gp4ELiDI/s800/HeaderRatio.png)

**概要 [#n7b8933d]
TableColumnの幅を比率で設定します。
* サンプルコード [#sourcecode]
#code(link){{
private void setTableHeaderColumnRaito() {
  TableColumnModel m = table.getColumnModel();
  List<Integer> list = getWidthRaitoArray();
  int total = table.getSize().width;
  double raito = total / (double) getRaitoTotal(list);
  for (int i = 0; i < m.getColumnCount() - 1; i++) {
    TableColumn col = m.getColumn(i);
    int colwidth = (int) (.5 + list.get(i) * raito);
    col.setPreferredWidth(colwidth);
    total -= colwidth;
  }
  // 最後のカラムで余りを解消
  m.getColumn(m.getColumnCount() - 1).setPreferredWidth(total);
  table.revalidate();
}
}}

#screenshot
* 解説 [#explanation]
上記のサンプルでは、`JTextField`にコロン区切りで入力した比率に従って各カラムヘッダの幅を調整しています。

**サンプルコード [#dc125241]
 private void setRaito() {
   javax.swing.SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       int[] list = getWidthRaitoArray();
       int total = getTotalColumnWidth(table);
       int raito = total/getRaitoTotal(table, list);
       for(int i=0;i<table.getColumnModel().getColumnCount()-1;i++) {
         TableColumn col = table.getColumnModel().getColumn(i);
         int colwidth = list[i]*raito;
         col.setMaxWidth(colwidth);
         total = total - colwidth;
       }
       //最後のカラムで誤差で誤差を吸収
       table.getColumnModel().getColumn(
         table.getColumnModel().getColumnCount()-1).setMaxWidth(total);
       table.revalidate();
     }
   });
 }
- `ComponentListener#componentResized(...)`がチェックされている場合:
-- `JScrollPane`に追加した`ComponentListener`でリサイズが実行されると全ての列幅を設定し直すのでフレームのサイズを変更してもカラムの比率は保持される
- `ComponentListener#componentResized(...)`がチェックされていない場合:
-- 列幅調整が`AUTO_RESIZE_SUBSEQUENT_COLUMNS`(デフォルト)なので、フレームをリサイズするとその幅の変更([https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JTable.html#doLayout-- デルタ])がリサイズ可能なすべての列に分散して加算減算される
--- このため入力されている比率とは異なる列幅になる
-- `TableColumn#setMaxWidth`メソッドでカラムの幅を指定する場合、マウスのドラッグによるリサイズは不可

-&jnlp;
-&jar;
-&zip;
* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JTable.html#doLayout-- デルタの分散 - JTable#doLayout() (Java Platform SE 8)]

**解説 [#r3b250ae]
上記のサンプルでは、テキストフィールドにコロン区切りで入力した比率に従って、ヘッダカラムの幅を調整するようになっています。

JScrollPaneにComponentListenerを追加して、リサイズ毎に初期化しているので、フレームのサイズを変更してもカラムの比率は保持されます。

TableColumn#setMaxWidthメソッドでカラムの幅を指定しているので、マウスのドラッグによるサイズの変更はできません。

起動時だけ比率を設定したい場合は、以下のようにTableColumn#setPreferredWidthメソッドを使用することで、マウスのドラッグによるサイズが可能になります。またComponentListenerを追加して初期化しなくても、フレームサイズ変更時には現在のカラム幅の比率から適当にリサイズしてくれます((逆にTableColumn#setPreferredWidthメソッドを使用している場合にComponentListenerを追加して初期化してしまうと、比率が微妙に食い違って奇妙な動きになってしまう))。

 int[] list = getWidthRaitoArray();
 int total = table.getColumnModel().getTotalColumnWidth();;
 int raito = total/getRaitoTotal(table, list);
 for(int i=0;i<table.getColumnModel().getColumnCount()-1;i++) {
   TableColumn col = table.getColumnModel().getColumn(i);
   int colwidth = list[i]*raito;
   // - table.getColumnModel().getColumnMargin();
   col.setPreferredWidth(colwidth);
   total = total - colwidth;
 }
 table.getColumnModel().getColumn(
   table.getColumnModel().getColumnCount()-1).setPreferredWidth(total);
 table.revalidate();

//**参考リンク
**コメント [#f4b5dfe7]
* コメント [#comment]
#comment
#comment