Расположение узлов в JTree - PullRequest
       27

Расположение узлов в JTree

4 голосов
/ 09 октября 2009

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

Дерево пользователя:

 -FolderA
   +FFA1
   -FA1
   -FA2
 -FolderB
   -FB1
 -File1
 -File2
 +FolderC
 -File3

Результирующее дерево:

-File1
 -File2
 -File3
 -FolderA   
   -FA1
   -FA2
   +FAF1
 -FolderB
   -FB1
 +FolderC

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

Большое спасибо.

Решение 1:

private void arrange(DefaultMutableTreeNode parent){
    DefaultMutableTreeNode sorted = new DefaultMutableTreeNode();
    List<DefaultMutableTreeNode> files = new ArrayList<DefaultMutableTreeNode>();
    List<DefaultMutableTreeNode> folders = new ArrayList<DefaultMutableTreeNode>();

    for (int i = 0; i < parent.getChildCount(); i++){
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getChildAt(i);
        int type = ((BusinessObject) node.getUserObject()).getType();
        if (type == BusinessObject.FILE)
            files.add(node);
        else{
            arrange(node);
            folders.add(node);
        }
    }
    for (int i = 0; i < files.size(); i++)
        sorted.add((DefaultMutableTreeNode) files.get(i));

    for (int i = 0; i < folders.size(); i++)
        sorted.add((DefaultMutableTreeNode) folders.get(i));

    while (sorted.getChildCount() > 0)
        parent.add((DefaultMutableTreeNode) sorted.getChildAt(0));

    sorted = null;
    files = null;
    folders = null;
}

Решение 2:

private void arrange(DefaultMutableTreeNode parent){
    DefaultMutableTreeNode sorted = new DefaultMutableTreeNode();
    List<DefaultMutableTreeNode> nodes = new ArrayList<DefaultMutableTreeNode>();

    for (int i = 0; i < parent.getChildCount(); i++){
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getChildAt(i);
        int type = ((BusinessObject) node.getUserObject()).getType();
        if (type == BusinessObject.FILE)
            nodes.add(node);
    }

    for (int i = 0; i < parent.getChildCount(); i++){
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent.getChildAt(i);
        int type = ((BusinessObject) node.getUserObject()).getType();
        if (type == BusinessObject.FOLDER){
            arrange(node);
            nodes.add(node);
        }
    }

    for (int i = 0; i < nodes.size(); i++)
        sorted.add((DefaultMutableTreeNode) nodes.get(i));

    while (sorted.getChildCount() > 0)
        parent.add((DefaultMutableTreeNode) sorted.getChildAt(0));

    sorted = null;
    nodes = null;
}

Ответы [ 5 ]

3 голосов
/ 01 апреля 2011

это на самом деле работает, как я использую его в моем приложении. Все мои узлы - это изменяемые по умолчанию триоды без изменений. Сортируемый узел передается и изменяется. Это делает массив дочерних узлов. Затем два массива текстов узлов, которые сортируются. Другой используется для поиска узлов в arralylist. Все узлы перемещаются из исходного узла, а затем добавляются обратно из массива. Создает заклинание, может быть излишне использовать массив, но они мне нравятся.

private void sortchildren(DefaultMutableTreeNode node) {
        ArrayList children = Collections.list(node.children());
        // for getting original location
        ArrayList<String> orgCnames = new ArrayList<String>();
        // new location
        ArrayList<String> cNames = new ArrayList<String>();
        //move the child to here so we can move them back
        DefaultMutableTreeNode temParent = new DefaultMutableTreeNode();
        for(Object child:children) {
            DefaultMutableTreeNode ch = (DefaultMutableTreeNode)child;
            temParent.insert(ch,0);
            cNames.add(ch.toString().toUpperCase());
            orgCnames.add(ch.toString().toUpperCase());
        }
        Collections.sort(cNames);
        for(String name:cNames) {
            // find the original location to get from children arrayList
            int indx = orgCnames.indexOf(name);
            node.insert((DefaultMutableTreeNode)children.get(indx),node.getChildCount());
        }
    }
3 голосов
/ 09 октября 2009

Я думаю, что оба хороших решения. Было довольно легко сказать, что они делают: вытащить файлы, вытащить папки, бросить их обратно в дерево в правильном порядке. Кроме того, рекурсивный вызов был простым и интуитивно понятным.

Выберите тот, который кажется вам наиболее естественным. Второе похоже на то, как я бы это сделал, но это только я, и в этом нет особой разницы.

Вы используете Java 5 или 6? Если это так, используйте для каждого цикла . Кроме того, вам не нужно очищать значения ваших приватных переменных в конце метода. Они все равно уходят, когда метод возвращается.

1 голос
/ 23 сентября 2016

В наше время с java 8 проще:

DefaultMutableTreeNode node; // node can't be null, it's an example

List<DefaultMutableTreeNode> childrenList = Collections.list(node.children());

Collections.sort(childrenList, (o1,o2) ->
((Node) o1.getUserObject()).getName().compareToIgnoreCase(((Node)o2.getUserObject()).getName()));

node.removeAllChildren();
childrenList.forEach(node::add);
1 голос
/ 04 октября 2012

Я немного изменил пример кода Майка, чтобы учесть дубликаты имен и сортировку папок перед файлами. В противном случае это сработало как сон. Спасибо, Майк.

public static void sortTreeNode(DefaultMutableTreeNode node) {
List<DefaultMutableTreeNode> children = Collections.list(node.children());
List<String> sortFileNames = new ArrayList<>();
List<String> sortFolderNames = new ArrayList<>();
List<String> sortNames = new ArrayList<>();
List<String> origNames = new ArrayList<>();
DefaultMutableTreeNode temParent = new DefaultMutableTreeNode();
for (int x = 0; x < children.size(); x++) {
    DefaultMutableTreeNode child = children.get(x);
    temParent.insert(child, 0);
    if (!child.isLeaf()) {
    sortFolderNames.add(ViewMethods.getStringForNode(child).toUpperCase() + x);
    origNames.add(ViewMethods.getStringForNode(child).toUpperCase() + x);
    if (child.getChildCount() > 0) {
        sortTreeNode(child);
    }
    } else {
    sortFileNames.add(ViewMethods.getStringForNode(child).toUpperCase() + x);
    origNames.add(ViewMethods.getStringForNode(child).toUpperCase() + x);
    }
}
Collections.sort(sortFolderNames);
Collections.sort(sortFileNames);
sortNames.addAll(sortFolderNames);
sortNames.addAll(sortFileNames);
for (String name : sortNames) {
    // find the original location to get from children arrayList
    int indx = origNames.indexOf(name);
    node.insert(children.get(indx), node.getChildCount());
}
}
0 голосов
/ 03 декабря 2012

Это очень просто: Поместить все листья папки в массив (с именем listen o_people)

    DefaultMutableTreeNode all_node = 
     new DefaultMutableTreeNode("Root folder");
    DefaultMutableTreeNode one_node;
    Vector sorted_people=new Vector();
    // a simple algorithm of sorting array
    for (int i=0;i&lt;o_people.length-1;i++){
    for (int j=i+1;j&lt;o_people.length;j++){
        if(o_people[j].toString().compareTo
           (o_people[i].toString())<0) {

            String permut=o_people[i].toString();
            o_people[i]=o_people[j];
            o_people[j]=permut;

        }

    }
    sorted_people.add(o_people[i]);

   //in my case the leaf is a JChechbox but you can put a String
    one_node = new DefaultMutableTreeNode
     ( new JCheckBox(o_people[i].toString(), boolien));
    all_node.add(one_node);
    }

    tree_model.setRoot(all_node);

Просто !!! не так ли?

...