概要

JTreeのノードを検索し、そのTreePathが条件に一致しないノードを非表示にするフィルタリングを行います。

サンプルコード

tree.setCellRenderer(new DefaultTreeCellRenderer() {
  private final JLabel emptyLabel = new JLabel();
  @Override public Component getTreeCellRendererComponent(
        JTree tree, Object value,
        boolean selected, boolean expanded, boolean leaf,
        int row, boolean hasFocus) {
    Component c = super.getTreeCellRendererComponent(
        tree, value, selected, expanded, leaf, row, hasFocus);
    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    FilterableNode uo = (FilterableNode) node.getUserObject();
    return uo.status ? c : emptyLabel;
  }
});
fireDocumentChangeEvent();
// ...

private void fireDocumentChangeEvent() {
  String q = field.getText();
  TreePath rtp = tree.getPathForRow(0);
  if (q.isEmpty()) {
    resetAll(tree, rtp, true);
    ((DefaultTreeModel) tree.getModel()).reload();
    // visitAll(tree, rtp, true);
  } else {
    visitAll(tree, rtp, false);
    searchTree(tree, rtp, q);
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、指定された条件に一致しないノードを高さ0TreeCellRendererで描画することで、ノードのフィルタリングを行っています。

  • TreePathに指定された接頭辞で始まるTreeNodeが含まれている場合、そのノードのUserObjectに表示フラグを立てる
    • 例: fooで検索した場合foodノード以下の子ノードも表示される
  • TreeCellRenderer内でUserObjectを取得し、非表示の場合は高さ0JLabelをレンダラーとして返す
    • tree.setRowHeight(-1);と設定しているので各ノードの描画を行うレンダラーの推奨サイズが行の高さとして使用される
  • 高さ0のノードに対しても関連ノード間を繋ぐ点線が引かれる場合がある(LookAndFeelに依存)のでこれを非表示にする場合は、UIManager.put("Tree.paintLines", Boolean.FALSE);、またはtree.putClientProperty("JTree.lineStyle", "None");などを使用する

参考リンク

コメント