TITLE:JTableの列固定とソート
#navi(../)
#tags()
RIGHT:Posted by &author(aterai); at 2008-11-10
*JTableの列固定とソート [#j1bd19e9]
列固定したJTableで、JDK 6 で導入されたTableRowSorterを使った行ソートを行います。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTMzes1hqI/AAAAAAAAAZw/-m-PZSFzYAk/s800/FixedColumnTableSorting.png)

**サンプルコード [#bb39c51e]
#code(link){{
fixedTable = new JTable(model);
table      = new JTable(model);
fixedTable.setSelectionModel(table.getSelectionModel());
fixedTable.setUpdateSelectionOnSort(false);
//table.setUpdateSelectionOnSort(true);

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.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

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

final JScrollPane scroll = new JScrollPane(table);
JViewport viewport = new JViewport();
viewport.setView(fixedTable);
viewport.setPreferredSize(fixedTable.getPreferredSize());
scroll.setRowHeader(viewport);
//scroll.setRowHeaderView(fixedTable);
//fixedTable.setPreferredScrollableViewportSize(fixedTable.getPreferredSize());
scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable.getTableHeader());
scroll.getViewport().setBackground(Color.WHITE);
viewport.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() {
  @Override public void stateChanged(ChangeEvent e) {
    JViewport viewport = (JViewport) e.getSource();
    scroll.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
  }
});
//</blockquote>
add(scroll);
}}

**解説 [#x610cfac]
左の固定テーブル(fixedTable)と、右のテーブル(table)に同じRowSorterを設定することで、列固定表でもソートできるようにしています。
ただし、上記のサンプルでは、ソート中に行の追加を行うと例外が発生するので、追加の前にsorter.setSortKeys(null);でSortKeysをクリアしています。
#code{{
add(new JButton(new AbstractAction("add") {
  @Override public void actionPerformed(ActionEvent e) {
    //List<? extends RowSorter.SortKey> keys = sorter.getSortKeys();
    sorter.setSortKeys(null);
    for(int i=0;i<100;i++) {
      model.addRow(new Object[] {i, i+1, "A"+i, "B"+i});
    }
    //sorter.setSortKeys(keys);
  }
}), BorderLayout.SOUTH);
}}

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

-以下を間違えてしていたため、描画がおかしくなっていた。
--JScrollPane#setRowHeaderView(Component)
--JScrollPane#setRowHeader(JViewport)

----
固定列でキーボードなどによるスクロールに対応するために以下のようなChangeListenerを追加しています。
-参考:[http://tips4java.wordpress.com/2008/11/05/fixed-column-table/ Fixed Column Table ≪ Java Tips Weblog]
#code{{
scroll.getRowHeader().addChangeListener(new ChangeListener() {
  @Override public void stateChanged(ChangeEvent e) {
    JViewport viewport = (JViewport) e.getSource();
    scroll.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
  }
});
}}

**参考リンク [#y3ae24e4]
-[http://www.google.com/search?q=FixedColumnExample.java FixedColumnExample.java]
-[http://tips4java.wordpress.com/2008/11/05/fixed-column-table/ Fixed Column Table ≪ Java Tips Weblog]

**コメント [#tda194b1]
- タブキーによるフォーカスの移動は・・・、まぁいいかな。 -- [[aterai]] &new{2008-11-10 (月) 14:26:25};
- 固定列は、数字でソートするように変更。 -- [[aterai]] &new{2008-11-10 (月) 15:27:19};
- どちらか片方のJTableを setUpdateSelectionOnSort(false); としてソート後、選択状態がおかしくならないように修正。 -- [[aterai]] &new{2010-10-23 (土) 03:13:02};
- 下記サイトは別の手法で列を固定しています。ご参考まで。<http://weblogs.java.net/blog/elevy/archive/2009/01/freezable_jtabl.html> -- [[panda]] &new{2010-12-22 (水) 15:30:06};
-- 情報どうもです。ポップアップで固定する列を決めると、固定列の右が水平スクロールで移動できるのですね。最初、固定の確認でヘッダ列をリサイズしてたので迷いました(^^;。固定中は、table.getTableHeader().setResizingAllowed(false); table.getTableHeader().setReorderingAllowed(false);とかで、列のリサイズ、移動を禁止したほうがいいかも。でも、ソートや行選択などが簡単にできるのは便利ですね。 -- [[aterai]] &new{2010-12-22 (水) 17:32:51};

#comment