Могу ли я остановить кэширование узлов JTree (в дереве файловой системы)?

У меня есть реализация JTree для каталогов в файловой системе. У меня проблема в том, что когда каталог удаляется или переименовывается, дерево по-прежнему показывает каталог в его родителях. Похоже, что родительское дерево не обновляется для каких-либо изменений после расширения узла.

Модель, которую я написал, не кэшируется (я прокомментировал, какое ограниченное кэширование у нее было) - это похоже на то, что сам JTree кэширует узел.

Код (модель является вложенным подклассом):

public class FileSystemTree
extends JTree
{

// *****************************************************************************
// INSTANCE CREATE/DELETE
// *****************************************************************************

public FileSystemTree() {
    this(new Model(null,null,null));
    }

public FileSystemTree(String startPath) {
    this(new Model(startPath,null,null));
    }

public FileSystemTree(FileSelector inc, FileSelector exc) {
    this(new Model(null,inc,exc));
    }

public FileSystemTree(String startPath, FileSelector inc, FileSelector exc) {
    this(new Model(startPath,inc,exc));
    }

private FileSystemTree(Model model) {
    super(model);

    //setLargeModel(true);
    setRootVisible(false);
    setShowsRootHandles(true);
    putClientProperty("JTree.lineStyle","Angled");
    }

// *****************************************************************************
// INSTANCE METHODS - ACCESSORS
// *****************************************************************************

public Object getRoot() {
    return getModel().getRoot();
    }

// *****************************************************************************
// INSTANCE METHODS
// *****************************************************************************

public String convertValueToText(Object value,boolean selected,boolean expanded,boolean leaf,int row,boolean hasFocus) {
    File                                fil=(File)value;

    return (fil.getName().length()!=0 ? fil.getName() : fil.getPath());
    }

// *****************************************************************************
// STATIC NESTED CLASSES - SUPPORTING MODEL
// *****************************************************************************

    static class Model
    extends Object
    implements TreeModel, FilenameFilter
    {

    private File                        root;                                   // tree root
    //ivate Map                         cache;                                  // caches child counts for directories
    private File[]                      fsRoots;                                // copy of file system roots
    private FileSelector                include;                                // inclusion selector
    private FileSelector                exclude;                                // exclusion selector
    private java.util.List              listeners=new ArrayList();

    public Model(String roo, FileSelector inc, FileSelector exc) {
        super();

        root=(roo==null ? DRIVES : new File(roo));
        //cache=new HashMap();
        fsRoots=(root==DRIVES ? rootList() : null);
        include=inc;
        exclude=exc;
        }

    // *****************************************************************************
    // METHODS - MODEL
    // *****************************************************************************

    public Object getRoot() {
        return root;
        }

    public Object getChild(Object parent, int index) {
        File                            dir=(File)parent;

        if(dir==DRIVES) {
            File[]   chl=fsRoots; //rootList();
            return (index<chl.length ? chl[index] : null);
            }
        else {
            String[] chl=dirList(dir);
            return (index<chl.length ? new File(dir,chl[index]) : null);
            }
        }

    public int getChildCount(Object parent) {
        File                            dir=(File)parent;
        //Integer                         cch=(Integer)cache.get(dir);

        //if(cch!=null) {
        //    return cch.intValue();
        //    }

        if(dir==DRIVES) {
            return fsRoots.length; //rootList().length;
            }
        else if(dir.isDirectory()) {
            return dirList(dir).length;
            }
        else {
            return 0;
            }
        }

    public boolean isLeaf(Object node) {
        return((File)node).isFile();
        }

    public void valueForPathChanged(TreePath path, Object newValue) {
        }

    public int getIndexOfChild(Object parent, Object child) {
        File                            dir=(File)parent;
        File                            fse=(File)child;

        if(dir==DRIVES) {
            File[] ca=fsRoots; //rootList();
            for(int xa=0; xa<ca.length; xa++) {
                if(fse.equals(ca[xa])) { return xa; }
                }
            }
        else {
            String[] ca=dirList(dir);
            for(int xa=0; xa<ca.length; ++xa) {
                if(fse.getName().equals(ca[xa])) { return xa; }
                }
            }
        return -1;
        }

     private File[] rootList() {
        File[]                          lst=File.listRoots();

        if(lst==null) { lst=new File[0]; }
        //cache.put(DRIVES,new Integer(lst.length));
        return lst;
        }

     private String[] dirList(File dir) {
        String[]                        lst=dir.list(this);

        if(lst==null) { lst=new String[0]; }
        //cache.put(dir,new Integer(lst.length));
        return lst;
        }

    // *****************************************************************************
    // METHODS - FILENAME FILTER
    // *****************************************************************************

    public boolean accept(File dir, String nam)  {
        return ((include==null || include.accept(dir,nam)) && (exclude==null || !exclude.accept(dir,nam)));
        }

    // *****************************************************************************
    // METHODS - LISTENER
    // *****************************************************************************

    public void addTreeModelListener(TreeModelListener listener) {
        if(listener != null && !listeners.contains(listener)) {
            listeners.add(listener);
            }
        }

    public void removeTreeModelListener(TreeModelListener listener) {
        if(listener != null) {
            listeners.remove(listener);
            }
        }

    public void fireTreeNodesChanged(TreeModelEvent evt) {
        Iterator                        itr=listeners.iterator();

        while(itr.hasNext()) {
            TreeModelListener listener=(TreeModelListener)itr.next();
            listener.treeNodesChanged(evt);
            }
        }

    public void fireTreeNodesInserted(TreeModelEvent evt) {
        Iterator                        itr=listeners.iterator();

        while(itr.hasNext()) {
            TreeModelListener listener=(TreeModelListener)itr.next();
            listener.treeNodesInserted(evt);
            }
        }

    public void fireTreeNodesRemoved(TreeModelEvent evt) {
        Iterator                        itr=listeners.iterator();

        while(itr.hasNext()) {
            TreeModelListener listener=(TreeModelListener)itr.next();
            listener.treeNodesRemoved(evt);
            }
        }

    public void fireTreeStructureChanged(TreeModelEvent evt) {
        Iterator                        itr=listeners.iterator();

        while(itr.hasNext()) {
            TreeModelListener listener=(TreeModelListener)itr.next();
            listener.treeStructureChanged(evt);
            }
        }
    } // END INNER CLASS

// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************

static private final File               DRIVES=new File("*DRIVES");             // marker for listing file system drives

} // END PUBLIC CLASS

person Lawrence Dol    schedule 15.03.2009    source источник


Ответы (3)


Модель отвечает за уведомление слушателей о любых изменениях в древовидной структуре. Дерево не будет обновляться без такого уведомления.

person Maurice Perry    schedule 15.03.2009
comment
Я неправильно понимал, как функционирует дерево; не понял, что мне пришлось использовать модель для уведомления об изменениях в файловой системе; в моем случае я точно знаю, что изменилось, поэтому запустить событие модели дерева было просто, как только я понял, что должен это сделать. - person Lawrence Dol; 16.03.2009

Вы можете написать некоторый фоновый поток, который ищет изменения в файловой системе и запускает некоторые события модификации модели, если вы обнаружите, что каталоги изменились.

person Mario Ortegón    schedule 15.03.2009

Не видя кода Модели, вы уверены, что она вызывается, например метод getChild?

person TofuBeer    schedule 16.03.2009
comment
@TofuBeer: код опубликован в вопросе - это вложенный класс в подклассе JTree. - person Lawrence Dol; 16.03.2009