5

JDialogに使用するJTreeノードの可視性に問題があります。モデルに新しいノードを追加したいのですが、Jtreeが更新されません。

奇妙なことに、setRootVisible(true)を設定した場合、ノードは正常に更新されます。

これがコードです。前もって感謝します

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class TestClass {

JTree tree;
DefaultTreeModel dm;
JDialog dialog;

public TestClass(){
    JFrame frame = new JFrame("title");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    JPanel showPane = new JPanel();
    showPane.setLayout(new BorderLayout()); 

    dm = new DefaultTreeModel(new DefaultMutableTreeNode("root"));
    tree = new JTree(dm);
    tree.setRootVisible(false);

    JButton button = new JButton("add node");
    button.addActionListener(new ActionListener(){

        public void actionPerformed(ActionEvent arg0) {
            DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();           
            dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount());

            int c = root.getChildCount();
            System.out.println("child count: " + c);

            for(int i=0; i<c; i++){
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i);
                System.out.println("has node:" + node.getUserObject().toString());
            }
        }

    });

    showPane.add(tree, BorderLayout.CENTER);
    showPane.add(button, BorderLayout.PAGE_END);

    JComponent[] inputComponents = new JComponent[] {showPane};

    Object[] opButtons = {"OK"};

    JOptionPane optPane = new JOptionPane(inputComponents       
            , JOptionPane.PLAIN_MESSAGE             
            , JOptionPane.CLOSED_OPTION             
            , null                                      
            , opButtons                             
            , opButtons[0]);                            

    optPane.setPreferredSize(new Dimension(400 ,250));

    dialog = optPane.createDialog(null, "Create new Application Node");
    dialog.setLocationRelativeTo(frame);
    dialog.setVisible(true);

    if(optPane.getValue() != null){
        System.exit(0);
    }

}

public static void main(String arg[]){
    TestClass myClass = new TestClass();
}

}

4

3 に答える 3

7

新しい子ノードを追加するたびに、新しいノードの親からルートへのパスを必ず展開してください。

DefaultMutableTreeNode newChild = new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1));
dm.insertNodeInto(newChild, root, root.getChildCount());
tree.expandPath(new TreePath(dm.getPathToRoot(newChild.getParent())));
于 2012-10-13T20:13:06.627 に答える
3

別の解決策も確認してください。

   DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); 
   model.reload(); 

APIによると:

このモデルが依存するTreeNodeを変更した場合は、reloadメソッドを呼び出します。モデルは、モデルが変更されたことをすべてのリスナーに通知します。

簡単に確認するには、次のことを試してください。

public void actionPerformed(ActionEvent arg0) {
   DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
   dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount());

   int c = root.getChildCount();
   System.out.println("child count: " + c);

   DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); // !!!
   model.reload();   // !!!

   for (int i = 0; i < c; i++) {
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i);
       System.out.println("has node:" + node.getUserObject().toString());
   }
}

詳細については、次の回答を参照してください。

于 2012-10-13T21:01:46.907 に答える
3

要約すると、@JBNizetによる答えは正しいです。

  • ノードを挿入しても、親の拡張状態には自動的に影響しません。
  • したがって、新しく挿入された子が表示されるようにするには、その親を展開する必要があります

子を表示するために少し代替APIを投入するには:

dm.makeVisible(new TreePath(newChild.getPath());

@Geoff Reedyによるコメントについて(私が太字で):

通常、JTreeのルートノードは展開されますが、ツリーが作成されるとき、ルートノードには子がないため、展開できません。

できないことはそれほど厳密ではありません。拡張できるかどうか(子がゼロの場合でも)は、実際にはモデルのisLeafの実装に依存します。間違いなく、その本質はそうではないので、根は(子供がいなくても)葉になることはありません:-)で達成することができます

final DefaultTreeModel model = new DefaultTreeModel(root) {

    @Override
    public boolean isLeaf(Object node) {
        if (isRoot(node)) {
            return false;
        }
        return super.isLeaf(node);
    }

    private boolean isRoot(Object node) {
        return node != null && node == getRoot();
    }

};

このような実装では、ルートは常に拡張され(ルートが表示されるかどうかに関係なく)、新しく挿入された直接の子は、明示的に表示されることなく表示されます。

于 2012-10-17T16:12:18.507 に答える