Sunday

Implementation of lazy loading (swing)

Hello, this is a example of displaying tree folder with lazy loading.
List of child nodes is retrieved when click on a node by using TreeWillExpandListener.

1. Class TreeDirectory
package jbohn.swing;
import java.awt.EventQueue;
import java.io.File;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.MutableTreeNode;

public class TreeDirectory extends JFrame implements TreeWillExpandListener
{
    private JTree jTree;
    private DefaultTreeModel treeModel;
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                TreeDirectory tree = new TreeDirectory();
                tree.initial();
                tree.setVisible(true);
            }
        });
    }
    private void initial()
    {
        this.add(getJTreeDirectory());
    }

    @Override
    public void treeWillCollapse(TreeExpansionEvent arg0)
            throws ExpandVetoException {
    }

    @Override
    public void treeWillExpand(TreeExpansionEvent arg0)
            throws ExpandVetoException {
        final TreeNode lazyNode =
                (TreeNode) arg0.getPath().getLastPathComponent();
        if( lazyNode.isFullyLoaded() )
        {
            return;
        }
        new SwingWorker<List<MutableTreeNode>, Void>(){
            @Override
            protected List<MutableTreeNode> doInBackground() throws Exception {
                // TODO Auto-generated method stub
                return lazyNode.loadChildren();
            }

            protected void done() {
                try {
                    for (MutableTreeNode node : get()) {
                        treeModel.insertNodeInto(node, lazyNode,
                                lazyNode.getChildCount());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.execute();
    }
    public JTree getJTreeDirectory() {
        if (jTree == null)
        {
            TreeNode root = new TreeNode(new File("C:\\"));
            treeModel = new DefaultTreeModel(root, true);
            jTree = new JTree(treeModel);
            jTree.setRootVisible(true);
            jTree.addTreeWillExpandListener(this);
            jTree.collapseRow(0);
        }
        return jTree;
    }
}


2. Class TreeNode
package jbohn.swing;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;

public class TreeNode extends DefaultMutableTreeNode
{
    public TreeNode(File file)
    {
        super(file);
        setAllowsChildren(file.isDirectory());
    }
    public List<MutableTreeNode> loadChildren() {
        List<MutableTreeNode> list = new ArrayList<>();
        File[] fileList = ((File) getUserObject()).listFiles();
        if (fileList == null) {
            fileList = new File[0];
        }
        for (File file : fileList) {
            list.add(new TreeNode(file));
        }
        return list;
    }
    public boolean isFullyLoaded()
    {
        return getChildCount() != 0 && getAllowsChildren();
    }
}