TITLE:JTableの列固定とソート

JTableの列固定とソート

Posted by terai at 2008-11-10

概要

列固定したJTableで、JDK 6 で導入されたTableRowSorterを使った行ソートを行います。

  • &jnlp;
  • &jar;
  • &zip;

#screenshot

サンプルコード

fixedTable = new JTable(model);
table      = new JTable(model);
fixedTable.setSelectionModel(table.getSelectionModel());

for(int i=model.getColumnCount()-1;i>=0;i--) {
  if(i<2) {
    table.removeColumn(table.getColumnModel().getColumn(i));
    fixedTable.getColumnModel().getColumn(i).setResizable(false);
  }else{
    fixedTable.removeColumn(fixedTable.getColumnModel().getColumn(i));
  }
}

fixedTable.setRowSorter(sorter);
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

table.setRowSorter(sorter);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

JScrollPane scroll = new JScrollPane(table);
//<ins>
JPanel wrapper = new JPanel(new BorderLayout(0,0));
wrapper.add(fixedTable);
scroll.setRowHeaderView(wrapper);
//</ins>
////<del>
//JViewport viewport = new JViewport();
//viewport.setView(fixedTable);
//viewport.setPreferredSize(fixedTable.getPreferredSize());
//fixedTable.setPreferredScrollableViewportSize(fixedTable.getPreferredSize());
//scroll.setRowHeaderView(viewport);
////</del>
scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
scroll.getViewport().setBackground(Color.WHITE);
//<blockquote cite="http://tips4java.wordpress.com/2008/11/05/fixed-column-table/">
//@auther Rob Camick
//@title Fixed Column Table ≪ Java Tips Weblog
scroll.getRowHeader().addChangeListener(new ChangeListener() {
  public void stateChanged(ChangeEvent e) {
    JViewport viewport = (JViewport) e.getSource();
    scroll.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
  }
});
//</blockquote>
add(scroll);

解説

左の固定テーブル(fixedTable)と、右のテーブル(table)に同じRowSorterを設定することで、列固定表でもソートできるようにしています。 ただし、上記のサンプルでは、ソート中に行の追加を行うと例外が発生するので、追加の前にsorter.setSortKeys(null);でSortKeysをクリアする必要があります。

add(new JButton(new AbstractAction("add") {
  public void actionPerformed(ActionEvent e) {
    sorter.setSortKeys(null);
    for(int i=0;i<100;i++) {
      model.addRow(new Object[] {
        i, i+1, "A"+i, "B"+i
      });
    }
  }
}), BorderLayout.SOUTH);

行を追加したとき、うまく描画されない場合があるので、以下のようなJPanelをラッパーとして使用しています。

final JScrollPane scroll = new JScrollPane(table);
//<ins>
final JPanel wrapper = new JPanel(new BorderLayout(0,0));
wrapper.add(fixedTable);
scroll.setRowHeaderView(wrapper);
fixedTable.setPreferredSize(new Dimension(160, Integer.MAX_VALUE-10000));
//</ins>
////<del>
//JViewport viewport = new JViewport();
//viewport.setView(fixedTable);
//viewport.setPreferredSize(fixedTable.getPreferredSize());
//fixedTable.setPreferredScrollableViewportSize(fixedTable.getPreferredSize());
//scroll.setRowHeaderView(viewport);
////</del>
scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
scroll.getViewport().setBackground(Color.WHITE);

固定列でキーボードなどによるスクロールに対応するために以下のようなChangeListenerを追加しています。

  • 参考:Fixed Column Table ≪ Java Tips Weblog
    scroll.getRowHeader().addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        JViewport viewport = (JViewport) e.getSource();
        scroll.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
      }
    });
    

参考リンク

コメント