1

问题的SSCCE如下。我正在动态填充JTree,但什么也没发生。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

public class DynamicTreeDemo extends JFrame
                        implements ActionListener {
private int newNodeSuffix = 1;
private static String ADD_COMMAND = "add";
private static String REMOVE_COMMAND = "remove";
private static String CLEAR_COMMAND = "clear";

private JTree jtrMainMenu;
DefaultMutableTreeNode   rootNode = null;
DefaultTreeModel treeModel;
public DynamicTreeDemo() {
    super(new BorderLayout());

    //Create the components.
    jtrMainMenu = new JTree();
    populateTree();

    JButton addButton = new JButton("Add");
    addButton.setActionCommand(ADD_COMMAND);
    addButton.addActionListener(this);

    JButton removeButton = new JButton("Remove");
    removeButton.setActionCommand(REMOVE_COMMAND);
    removeButton.addActionListener(this);

    JButton clearButton = new JButton("Clear");
    clearButton.setActionCommand(CLEAR_COMMAND);
    clearButton.addActionListener(this);

    //Lay everything out.
    jtrMainMenu.setPreferredSize(new Dimension(300, 150));
    add(jtrMainMenu, BorderLayout.CENTER);

    JPanel panel = new JPanel(new GridLayout(0,3));
    panel.add(addButton);
    panel.add(removeButton); 
    panel.add(clearButton);
add(panel, BorderLayout.SOUTH);
}


    public void populateTree() {
  Vector<Vector<String>> data =GetDataFromDB();           
 java.util.List<String> list =GetListFromDB();
        int i=0;;
 int size=list.size();
 treeModel=(DefaultTreeModel)jtrMainMenu.getModel();  

 ((DefaultMutableTreeNode)  (treeModel.getRoot())).removeAllChildren();
 treeModel.reload();
 rootNode = new DefaultMutableTreeNode("JewelleryERPApplication");
 treeModel=new DefaultTreeModel(rootNode);


 DefaultMutableTreeNode p1=null, p2=null,p3=null,p4=null,p5=null;


     while(i<size){

        if(list.get(i).length()==2){
          p1 = addObject(null, data.get(i).elementAt(1),true);  

        }else 
        if(list.get(i).length()==4){
           p2 = addObject(p1, data.get(i).elementAt(1),true);   

     }else if
       (list.get(i).length()==6){
             p3 = addObject(p2, data.get(i).elementAt(1),true);   

     }
     else if
       (list.get(i).length()==8){
             p4 = addObject(p3, data.get(i).elementAt(1),true);    

     }  
     else if
       (list.get(i).length()==10){
             p5 = addObject(p4, data.get(i).elementAt(1),true);    

     }      
         i++;
     }

    jtrMainMenu.setModel(treeModel);
   ((DefaultMutableTreeNode)  (treeModel.getRoot())).getChildCount();
    jtrMainMenu.revalidate();
    jtrMainMenu.repaint();
}


public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                        Object child, 
                                        boolean shouldBeVisible) {


          DefaultMutableTreeNode childNode = 
            new DefaultMutableTreeNode(child);



    if (parent == null) {
        parent = rootNode;
    }

//It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
    treeModel.insertNodeInto(childNode, parent, 
                             parent.getChildCount());

     jtrMainMenu.setModel(treeModel);

    //Make sure the user can see the lovely new node.
    if (shouldBeVisible) {
        jtrMainMenu.scrollPathToVisible(new TreePath(childNode.getPath()));
    }

    return childNode;
} 

/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("DynamicTreeDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    DynamicTreeDemo newContentPane = new DynamicTreeDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}
4

1 回答 1

4

你的代码有很多问题,但是......你遇到的主要问题(我认为)是当你重新加载模型时,默认情况下根节点是折叠的。

如果根节点被隐藏和/或它的句柄被隐藏,它将看起来好像没有加载任何内容。

取消隐藏这些元素以进行测试。

重新加载模型后,您还可以展开根节点...

在此处输入图像描述

!!警告 !!不要在你的根目录上运行它!它将扫描所有子目录,这可能需要更多时间,然后您实际上愿意等待:P

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

public class FileTree {

    public static void main(String[] args) {
        new FileTree();
    }

    public FileTree() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private DefaultTreeModel model;
        private JTree tree;

        public TestPane() {
            setLayout(new BorderLayout());

            tree = new JTree();
            File rootFile = new File(".");
            DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootFile);
            model = new DefaultTreeModel(root);

            tree.setModel(model);
            tree.setRootVisible(true);
            tree.setShowsRootHandles(true);

            add(new JScrollPane(tree));

            JButton load = new JButton("Load");
            add(load, BorderLayout.SOUTH);

            load.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

                    DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
                    root.removeAllChildren();
                    model.reload();
                    File rootFile = (File) root.getUserObject();

                    addFiles(rootFile, model, root);

                    tree.expandPath(new TreePath(root));

                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void addFiles(File rootFile, DefaultTreeModel model, DefaultMutableTreeNode root) {

            for (File file : rootFile.listFiles()) {
                DefaultMutableTreeNode child = new DefaultMutableTreeNode(file);
                model.insertNodeInto(child, root, root.getChildCount());
                if (file.isDirectory()) {
                    addFiles(file, model, child);
                }
            }

        }
    }
}

代码审查

您应该避免直接从JFrame. 从您的示例的外观来看,您不是,而是将其入侵,但无论如何都是不可取的...

这...

jtrMainMenu.setPreferredSize(new Dimension(300, 150));
add(jtrMainMenu, BorderLayout.CENTER);

这是不可取的。 JTree应添加到JScrollPane.

这...

private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("DynamicTreeDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    BadTree newContentPane = new BadTree();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

也不起作用(基于您的示例),因为任何扩展的内容Window都不能添加到任何其他扩展的容器中Window

除非您的基础组件是从 扩展的JComponent,否则其他组件必须是不透明的(JLabel显然是一个例外),因此将 设置newContentPane为不透明可能是一个静音点。

于 2013-03-05T04:50:17.307 回答