• title: JTableのリサイズで最後のTableColumnのみリサイズする tags: [JTable, JTableHeader, TableColumn] author: aterai pubdate: 2014-05-26T00:01:15+09:00

概要

JTableがリサイズされた場合、最後にあるTableColumnがその幅の変更を吸収するように設定します。主に、java - JTable columns doesnt resize probably when JFrame resize - Stack Overflowの回答からソースを引用しています。

サンプルコード

private final JTable table = new JTable(100, 3) {
  private transient ComponentListener resizeHandler;
  @Override public void updateUI() {
    removeComponentListener(resizeHandler);
    super.updateUI();
    resizeHandler = new ComponentAdapter() {
      @Override public void componentResized(ComponentEvent e) {
        JTable table = (JTable) e.getComponent();
        JTableHeader tableHeader = table.getTableHeader();
        if (tableHeader != null) {
          tableHeader.setResizingColumn(null);
        }
      }
    };
    addComponentListener(resizeHandler);
  }
  //http://stackoverflow.com/questions/16368343/jtable-resize-only-selected-column-when-container-size-changes
  //http://stackoverflow.com/questions/23201818/jtable-columns-doesnt-resize-probably-when-jframe-resize
  @Override public void doLayout() {
    if (tableHeader != null && autoResizeMode != AUTO_RESIZE_OFF && check.isSelected()) {
      TableColumn resizingColumn = tableHeader.getResizingColumn();
      if (resizingColumn == null) {
        TableColumnModel tcm = getColumnModel();
        int lastColumn = tcm.getColumnCount() - 1;
        tableHeader.setResizingColumn(tcm.getColumn(lastColumn));
      }
    }
    super.doLayout();
  }
};
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JTable#doLayout()をオーバーライドして、JFrameがリサイズされた、JTableJTableHeaderもリサイズされたら、JTableHeader.setResizingColumn(...)で最後のTableColumnを設定し、幅の変更をすべて吸収するようにしています。

  • 注:
    • table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);を設定しても、JTableHeader自体のリサイズではすべてのTableColumnの幅が均等に変化する
    • 列を入れ替えた場合でも、表示上最後にあるTableColumnがリサイズされる
    • チェックボックスで設定を切り替えているため、JTableComponentListenerを追加して、変更ごとにJTableHeader.setResizingColumn(null)でリセット
    • 以下のように、JTable#doLayout()をオーバーライドではなく、ComponentListenerの追加でも同様の動作をするように設定することができるが、リサイズ開始時に最後のTableColumnにも幅の変更が適用されてしまう(先にJTable#doLayout()が実行される)
JTable table2 = new JTable(100, 3);
table2.getTableHeader().addComponentListener(new ComponentAdapter() {
  @Override public void componentResized(ComponentEvent e) {
    JTableHeader tableHeader = (JTableHeader) e.getComponent();
    if (tableHeader == null) {
      return;
    }
    if (check.isSelected()) {
      TableColumnModel tcm = tableHeader.getTable().getColumnModel();
      int lastColumn = tcm.getColumnCount() - 1;
      tableHeader.setResizingColumn(tcm.getColumn(lastColumn));
    } else {
      tableHeader.setResizingColumn(null);
    }
  }
});

参考リンク

コメント