---
category: swing
folder: AddNode
title: JTreeのノード追加、削除
tags: [JTree, JPopupMenu, TreeNode, TreeModel]
author: aterai
pubdate: 2011-05-02T16:45:24+09:00
description: JTreeのノードを選択してJPopupMenuを開き、そのノードの削除や名前変更、子ノードの追加を行います。
image: https://lh6.googleusercontent.com/_9Z4BYR88imo/Tb5bkDzXJHI/AAAAAAAAA6c/qxz0Vzwy4Ts/s800/AddNode.png
---
* 概要 [#summary]
`JTree`のノードを選択して`JPopupMenu`を開き、そのノードの削除や名前変更、子ノードの追加を行います。

#download(https://lh6.googleusercontent.com/_9Z4BYR88imo/Tb5bkDzXJHI/AAAAAAAAA6c/qxz0Vzwy4Ts/s800/AddNode.png)

* サンプルコード [#sourcecode]
#code(link){{
class TreePopupMenu extends JPopupMenu {
  private TreePath path;
  public TreePopupMenu() {
    super();
    add(new AbstractAction("add") {
      @Override public void actionPerformed(ActionEvent e) {
        JTree tree = (JTree) getInvoker();
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
        DefaultMutableTreeNode parent =
          (DefaultMutableTreeNode) path.getLastPathComponent();
        DefaultMutableTreeNode child  = new DefaultMutableTreeNode("New");
        model.insertNodeInto(child, parent, parent.getChildCount());
        // parent.add(child);
        // model.reload(); //= model.nodeStructureChanged(parent);
        // model.reload(); // = model.nodeStructureChanged(parent);
        tree.expandPath(path);
      }
    });
    add(new AbstractAction("remove") {
      @Override public void actionPerformed(ActionEvent e) {
        JTree tree = (JTree) getInvoker();
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
        DefaultMutableTreeNode node =
          (DefaultMutableTreeNode) path.getLastPathComponent();
        // if (path.getParentPath() != null) {
        if (!node.isRoot()) {
          model.removeNodeFromParent(node);
        }
      }
    });
  }

  @Override public void show(Component c, int x, int y) {
    JTree tree = (JTree) c;
    TreePath[] tsp = tree.getSelectionPaths();
    path = tree.getPathForLocation(x, y);
    if (path != null && Arrays.asList(tsp).contains(path)) {
      super.show(c, x, y);
    }
  }
}
}}

* 解説 [#explanation]
上記のサンプルでは、`JPopupMenu`を使用して選択したノードに対して子ノードの追加、削除、名前変更ができます。

- 追加
-- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/tree/DefaultTreeModel.html#insertNodeInto-javax.swing.tree.MutableTreeNode-javax.swing.tree.MutableTreeNode-int- DefaultTreeModel#insertNodeInto(...)]メソッドを使用して、ノードを追加
- 追加とリロード
-- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/tree/DefaultMutableTreeNode.html#add-javax.swing.tree.MutableTreeNode- DefaultMutableTreeNode#add(MutableTreeNode)]メソッドを使ってノードを追加し、[https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/tree/DefaultTreeModel.html#reload-javax.swing.tree.TreeNode- DefaultTreeModel#reload(...)]、または[https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/tree/DefaultTreeModel.html#nodeStructureChanged-javax.swing.tree.TreeNode- DefaultTreeModel#nodeStructureChanged(TreeNode)]メソッドで更新を通知
--- 兄弟ノードの展開状態などがリセットされてしまう
- 削除
-- ルートノードでない場合(`DefaultMutableTreeNode#isRoot()`が`false`)、[https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/tree/DefaultTreeModel.html#removeNodeFromParent-javax.swing.tree.MutableTreeNode- DefaultTreeModel#removeNodeFromParent(MutableTreeNode)]メソッドで削除
- 名前変更
-- [[JTreeのノード編集をPopupからのみに制限する>Swing/StartEditingPopupMenu]]と同じ
#code{{
model.valueForPathChanged(path, str);
// もしくは、
// leaf.setUserObject(str);
// model.nodeChanged(leaf);
}}

* 参考リンク [#reference]
- [[JTreeのノード上でJPopupMenuを表示 >Swing/TreeNodePopupMenu]]
- [[JTreeのノード編集をPopupからのみに制限する>Swing/StartEditingPopupMenu]]
- [[JTreeの選択されたノードの前後に新規ノードを挿入する>Swing/InsertSiblingNode]]

* コメント [#comment]
#comment
- ソースなどのリンク切れを修正。 -- &user(aterai); &new{2011-05-06 (金) 18:46:23};

#comment