久しぶりにSwingでプログラミングをしていてTableTree的なことをやりたかったので、これまた久しぶりのSwingXにあるJXTreeTableを使ってみました。
JTableなどでもそうですが、JXTreeTableではJXTreeTable本体に加えてデータを表すTreeTableNodeと、それを表示するためのTreeTableModelを用意する必要があります。JFaceでいうとモデルがTreeTableNode、コンテンツプロバイダとラベルプロバイダを組み合わせたものがTreeTableModelに相当します。
試しに作ってみたのはこんな感じ。まずはTreeTableModelです。
public class SampleTreeTableModel extends DefaultTreeTableModel { private static final int INDEX_NAME = 0; private static final int INDEX_SIZE = 1; @Override public boolean isLeaf(Object node) { File file = (File) ((DefaultMutableTreeTableNode) node).getUserObject(); return file.isFile(); } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int column) { switch(column){ case INDEX_NAME: return "名前"; case INDEX_SIZE: return "サイズ"; default: return null; } } @Override public Object getValueAt(Object node, int column) { File file= (File) ((DefaultMutableTreeTableNode) node).getUserObject(); switch(column){ case INDEX_NAME: return file.getName(); case INDEX_SIZE: return file.isFile() ? file.length() : ""; default: return null; } } }
以下のような感じで使います。
private JXTreeTable buildTreeTable(){ SampleTreeTableModel model = new SampleTreeTableModel(); JXTreeTable treeTable = new JXTreeTable(model); model.setRoot(wrapToTreeTableNode(new File("..."))); return treeTable; } private DefaultMutableTreeTableNode wrapToTreeTableNode(File file){ DefaultMutableTreeTableNode node = new DefaultMutableTreeTableNode(file); for(File child: file.listFiles()){ if(child.isFile()){ node.add(new DefaultMutableTreeTableNode(child)); } else { node.add(wrapToTreeTableNode(child)); } } return node; }
んで、表示はこんな感じになります。
ここでは初期化時にすべてのノードを作成していますが、TreeTableNodeもしくはTreeTableModelを作りこめば展開されたタイミングでノードを生成するような動きも実現できます。TreeTableModelを完全に自作すれば任意のオブジェクトをノードとして使うこともできそう…。
ところでSwingXって去年の11月に1.6がリリースされています。まだ生きてたんですね…。