JTree отображает узлы, которые должны расширяться как конечные узлы.

У меня есть этот проект, в котором моя программа извлекает файлы из образа диска операционной системы и сохраняет их данные в базе данных, а другая функция извлекает файлы из базы данных и сохраняет их в списке (мой собственный тип объекта) и должна создать JTree после извлечения их путей (также хранящихся в базе данных) и разделения строк пути на основе косых черт, чтобы файлы внутри различных папок были конечными узлами, а папки — родительскими. Извлечение файлов работает отлично, но я думаю, что что-то не так с созданием JTree, поскольку некоторые папки отображаются как конечные узлы в JTree. Вот скриншот:

вы можете видеть, что папки /home и /usr являются конечными узлами

Позвольте мне рассказать вам, как выглядит мой код:

public class ActiveCase {   
private void populateList(){
    //a function that fetches a list of files from a database and stores it in a list
 List<AbstractFile> l = *a query function that stores the files in the list*;
listFiles(l);
}

public void listFiles(List<AbstractFile> fl){    
    ArrayList<TreePath> te = new ArrayList<TreePath>();
    try {           
        for(AbstractFile file : fl){
        //don't worry about the isDir() and getName() functions they work                               
        if(!file.isDir() && !file.getName().startsWith(".")){                                        
        te.add(new TreePath(("File list"+formatPath(file.getUniquePath())).split("/")));
        }
    }
    } catch (TskCoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   

        TreeModel tmClean = new TreePathsTreeModel("File list", te);
        cleanPanel.add(new JTree(tmClean));
}

private static String formatPath(String uniquePath){
    String[] pathSegments = uniquePath.split("/");
    int index = 3;
    StringBuilder strbuf = new StringBuilder();
    for (; index < pathSegments.length; ++index) {
        if (!pathSegments[index].isEmpty()) {
            strbuf.append("/").append(pathSegments[index]);
        }
    }   
    return strbuf.toString();
}        

}

И у меня есть класс TreePathsTreeModel, реализующий TreeModel:

    public class TreePathsTreeModel implements TreeModel {
      private final ArrayList<TreePath> paths;
      private final String root;

      public TreePathsTreeModel(String root, ArrayList<TreePath> te) {
        this.root = root;
        this.paths = te;
        //a little test print statement to see if the TreePath list is in the right format
        for(TreePath t : paths){
            System.out.println(t.toString());
        }
      }
      @Override
      public Object getRoot() {
        return this.root;
      }

      @Override
      public Object getChild(Object parent, int index) {
        try {
          return getChildren(parent).get(index);
        } catch (IndexOutOfBoundsException ex) {
          return null;
        }
      }

      @Override
      public int getChildCount(Object parent) {
        return getChildren(parent).size();
      }

      @Override
      public boolean isLeaf(Object node) {
        for (int i = 0; i < paths.size(); i++) {
          TreePath treePath = paths.get(i);
          if (treePath.getLastPathComponent().equals(node))
            return true;
        }
        return false;
      }

      // This method is only required for editable trees, so it is not
      // implemented here.
      @Override
      public void valueForPathChanged(TreePath path, Object newValue) {
        //throw new UnsupportedOperationException("Not supported yet.");
      }

      @Override
      public int getIndexOfChild(Object parent, Object child) {
        return getChildren(parent).indexOf(child);
      }

      // This TreeModel never fires any events (since it is not editable)
      // so event listener registration methods are left unimplemented
      @Override
      public void addTreeModelListener(TreeModelListener l) {
        //throw new UnsupportedOperationException("Not supported yet.");
      }

      @Override
      public void removeTreeModelListener(TreeModelListener l) {
        //throw new UnsupportedOperationException("Not supported yet.");
      }
              //search all paths in list for given object 
              //return every item one level further than it
      private ArrayList<String> getChildren(Object parent) {
        ArrayList<String> children = new ArrayList<String>();
        for (int i = 0; i < this.paths.size(); i++) {
          ArrayList<Object> pathObjects = new ArrayList<Object>( Arrays.asList(this.paths.get(i).getPath()) );
          for (Iterator<Object> it = pathObjects.iterator(); it.hasNext();) {
            Object parentCandidate = it.next();
            if (parentCandidate.equals(parent)) {
              Iterator<Object> checker = it;
              try {
                String child = new DefaultMutableTreeNode( checker.next() ).toString();
                if ( !children.contains(child) )
                  children.add (child);
              } catch (NoSuchElementException ex) {

              } 
            }
          }
        }
        return children;
      }

    }

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

...
[File list, dev, tty0]
[File list, dev, tty1]
[File list, dev, tty2]
[File list, dev, tty3]
[File list, dev, tty4]
[File list, dev, tty5]
[File list, dev, tty6]
[File list, dev, tty7]
[File list, dev, tty8]
[File list, dev, tty9]
[File list, dev, urandom]
[File list, dev, zero]
[File list, home, mainvm, examples.desktop]
[File list, home, mainvm, .cache, wallpaper, 0_5_1920_950_792beab7550410d531e55f95b449f135]
[File list, home, mainvm, .cache, upstart, unity7.log.2.gz]
[File list, home, mainvm, .cache, upstart, ssh-agent.log.2.gz]
[File list, home, mainvm, .cache, upstart, gnome-keyring-ssh.log.1.gz]
[File list, home, mainvm, .cache, upstart, dbus.log]
[File list, home, mainvm, .cache, upstart, unity7.log]
[File list, home, mainvm, .cache, upstart, hud.log]
[File list, home, mainvm, .cache, upstart, upstart-event-bridge.log.2.gz]
[File list, home, mainvm, .cache, upstart, unity7.log.1.gz]
[File list, home, mainvm, .cache, upstart, unity-settings-daemon.log.2.gz]
[File list, home, mainvm, .cache, upstart, unity-panel-service.log.2.gz]
[File list, home, mainvm, .cache, upstart, hud.log.1.gz]
[File list, home, mainvm, .cache, upstart, window-stack-bridge.log.2.gz]
[File list, home, mainvm, .cache, upstart, gpg-agent.log.2.gz]
[File list, home, mainvm, .cache, upstart, ssh-agent.log.1.gz]
[File list, home, mainvm, .cache, upstart, window-stack-bridge.log.1.gz]
[File list, home, mainvm, .cache, upstart, unity-panel-service.log]
[File list, home, mainvm, .cache, upstart, unity-settings-daemon.log.1.gz]
[File list, home, mainvm, .cache, upstart, unity-panel-service.log.1.gz]
[File list, home, mainvm, .cache, upstart, dbus.log.2.gz]
[File list, home, mainvm, .cache, upstart, dbus.log.1.gz]
[File list, home, mainvm, .cache, upstart, gnome-keyring-ssh.log.2.gz]
[File list, home, mainvm, .cache, upstart, gpg-agent.log.1.gz]
[File list, home, mainvm, .cache, upstart, indicator-sound.log.2.gz]
[File list, home, mainvm, .cache, upstart, indicator-sound.log.1.gz]
[File list, home, mainvm, .cache, upstart, upstart-event-bridge.log.1.gz]
[File list, home, mainvm, .cache, ibus, bus, registry.F0VAPY]
...
[File list, home, mainvm, .local, share, recently-used.xbel.49E0TY]
[File list, home, mainvm, .local, share, recently-used.xbel]
[File list, home, mainvm, .gnupg, gnupg_spawn_agent_sentinel.lock]
[File list, home, mainvm, .gnupg, S.gpg-agent]
[File list, lib, apparmor, functions]
[File list, lib, apparmor, profile-load]
[File list, lib, brltty, brltty.sh]
[File list, lib, brltty, libbrlttybal.so]
[File list, lib, brltty, libbrlttybat.so]
[File list, lib, brltty, libbrlttybba.so]
[File list, lib, brltty, libbrlttybbc.so]
[File list, lib, brltty, libbrlttybbd.so]
[File list, lib, brltty, libbrlttybbg.so]
[File list, lib, brltty, libbrlttybbl.so]
[File list, lib, brltty, libbrlttybbm.so]
[File list, lib, brltty, libbrlttybbn.so]
[File list, lib, brltty, libbrlttybcb.so]
[File list, lib, brltty, libbrlttybce.so]
[File list, lib, brltty, libbrlttybec.so]
[File list, lib, brltty, libbrlttybeu.so]
...

Может, у меня под носом что-то есть, что я упускаю. Это может быть и глупой ошибкой. Любые идеи? Это мой выпускной проект в колледже, пожалуйста, помогите!


person Aayush Pathak    schedule 06.03.2017    source источник


Ответы (1)


Ошибка, скорее всего, связана с методом isLeaf(Object node) вашего TreeModel.
Посмотрите javadoc TreeModel.isLeaf(Object node):

Возвращает true, если node является листом. Этот метод может вернуть false, даже если node не имеет дочерних элементов. Например, каталог в файловой системе может не содержать файлов; узел, представляющий каталог, не является листом, но у него также нет потомков.

Таким образом, в случае каталога (даже пустого каталога) вам нужно вернуть false вместо true.

person Thomas Fritsch    schedule 06.03.2017
comment
Спасибо! все, что мне нужно было сделать, это добавить еще одно условие в isLeaf() для проверки наличия пустых папок, и это сработало! Большое спасибо!!!! - person Aayush Pathak; 06.03.2017