JTree отображает узлы, которые должны быть расширены как конечные узлы
У меня есть этот проект, где моя программа извлекает файлы из образа диска операционной системы и сохраняет их данные в базе данных, а другая функция извлекает файлы из базы данных и сохраняет их в списке (мой собственный тип объекта) и должна создать JTree. после извлечения их путей (также хранящихся в базе данных) и разделения строк пути на основе слешей, чтобы файлы внутри различных папок были конечными узлами, а папки - родителями. Выборка файлов работает отлично, но я думаю, что что-то не так с созданием JTree, так как некоторые папки отображаются как листовые узлы в JTree. Вот скриншот:
Позвольте мне рассказать вам, как выглядит мой код:
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]
...
Может быть, что-то прямо под моим носом, что я скучаю. Это может быть глупой ошибкой. Есть идеи? Это мой последний год обучения в колледже, пожалуйста, помогите!
1 ответ
Ошибка, скорее всего, в isLeaf(Object node)
метод вашего TreeModel
,
Посмотрите на Javadoc TreeModel.isLeaf(Object node)
:
Возвращает
true
еслиnode
это лист. Для этого метода возможно возвращениеfalse
даже еслиnode
не имеет детей Например, каталог в файловой системе может не содержать файлов; узел, представляющий каталог, не является листом, но он также не имеет дочерних элементов.
Таким образом, в случае каталога (даже пустой каталог) вам необходимо вернуть false
вместо true
,