【问题标题】:Sort Jtree Node Alphabetically按字母顺序对 Jtree 节点进行排序
【发布时间】:2012-03-31 15:24:41
【问题描述】:

我已加载我的 JTree 以查看我的目录结构,如我的代码和输出图像中所示。 在这里,树节点默认按字母顺序排序,但我的另一个要求是我想根据目录名称的第二个名称对所有节点进行排序,而无需实际重命名目录。 我已在需要对 JTree 节点进行排序的名称下划线。请给我一些建议。

import java.io.File;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class FILE_NAME {
public static void main(String[] args) {
       JFrame frame = new JFrame("My Jtree");

       File root = new File("C:/java");
       JTree tree = new JTree(new FileTreeModel(root));
       frame.setSize(300, 300);
       frame.setVisible(true);
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.add(tree);
       frame.setVisible(true);            
      }
    }

class FileTreeModel implements TreeModel {

protected File root;

public FileTreeModel(File root) {
    this.root = root;
}

@Override
public Object getRoot() {
    return root;
}

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

@Override
public int getChildCount(Object parent) {
    String[] children = ((File) parent).list();
    if (children == null) {
        return 0;
    }
    return children.length;
}

@Override
public Object getChild(Object parent, int index) {
    String[] children = ((File) parent).list();
    if ((children == null) || (index == children.length)) {
        return null;
    }
    return new File((File) parent, children[index]);
}

@Override
public int getIndexOfChild(Object parent, Object child) {
    String[] children = ((File) parent).list();
    String childname = ((File) child).getName();
    if (children == null) {
        return -1;
    }
    for (int i = 0; i == children.length; i++) {
        if (childname.equals(children[i])) {
            return i;
        }
    }
    return -1;
}

@Override
public void valueForPathChanged(TreePath path, Object newvalue) {
}

@Override
public void addTreeModelListener(TreeModelListener l) {
}

@Override
public void removeTreeModelListener(TreeModelListener l) {
}
}

输出

【问题讨论】:

  • “请给我一些建议” 1) 描述你尝试过的东西。 2) 提出问题。
  • 嗯,我还在努力,很快就会通知你
  • 如果您不需要动态排序,最简单的方法是在构建 TreeModel 时对其进行排序

标签: java swing jtree


【解决方案1】:

您可以使用使用 Comparator 的 Arrays.sort() 方法,并编写自己的比较器,该比较器按照您自己的规则比较条目,如下所示:

String[] children = ((File) parent).list();
Arrays.sort(children, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        // do your comparison
    }
});

在模型方法中它会过载,因此您可以考虑将目录列表保存在某些模型私有字段中并检查目录是否在模型方法调用中没有更改(比较 File.lastModified() 会有所帮助)。如果是 - 保存新列表。

【讨论】:

    【解决方案2】:

    事情是这样的:

    public void sortTree() {
        treeModel.reload(sort(rootNode));
    }
    
    public DefaultMutableTreeNode sort(DefaultMutableTreeNode node) {
    
        //sort alphabetically
        for(int i = 0; i < node.getChildCount() - 1; i++) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
            String nt = child.getUserObject().toString();
    
            for(int j = i + 1; j <= node.getChildCount() - 1; j++) {
                DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
                String np = prevNode.getUserObject().toString();
    
                System.out.println(nt + " " + np);
                if(nt.compareToIgnoreCase(np) > 0) {
                    node.insert(child, j);
                    node.insert(prevNode, i);
                }
            }
            if(child.getChildCount() > 0) {
                sort(child);
            }
        }
    
        //put folders first - normal on Windows and some flavors of Linux but not on Mac OS X.
        for(int i = 0; i < node.getChildCount() - 1; i++) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
            for(int j = i + 1; j <= node.getChildCount() - 1; j++) {
                DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
    
                if(!prevNode.isLeaf() && child.isLeaf()) {
                    node.insert(child, j);
                    node.insert(prevNode, i);
                }
            }
        }
    
        return node;
    
    }
    

    【讨论】:

    • 此代码无法正常工作。在内部循环内交换节点会导致后续比较使用错误的节点。如果需要,最好搜索最低值并在最后交换。
    • 两个循环也过早结束。代码仅下降到具有两个或更多子级的文件夹中,并且从不比较最后一个子级。
    【解决方案3】:

    最灵活的解决方案是构建DefaultMutableTreeNode 的简单扩展,每次添加新元素时对节点的子节点进行排序(总体思路归功于this article):

    public class SimpleTreeNode
    extends DefaultMutableTreeNode
    {
        private final Comparator comparator;
    
        public SimpleTreeNode(Object userObject, Comparator comparator)
        {
            super(userObject);
            this.comparator = comparator;
        }
    
        public SimpleTreeNode(Object userObject)
        {
            this(userObject,null);
        }
    
        @Override
        public void add(MutableTreeNode newChild)
        {
            super.add(newChild);
            if (this.comparator != null)
            {
                Collections.sort(this.children,this.comparator);
            }
        }
    }
    

    此解决方案非常灵活,因为它允许您对树的每个级别甚至每个文件夹都有不同的排序方法。 (当然,您也可以很容易地在任何地方使用相同或不使用Comparator。)

    如果这对任何人都有帮助,请参阅下面我与 SimpleTreeNode 一起使用的两种排序方法:

    public class Comparators
    {
        /** Allows alphabetical or reverse-alphabetical sorting
         * 
         */
    
        public static class AlphabeticalComparator
        implements Comparator
        {
            private final boolean order;
    
            public AlphabeticalComparator()
            {
                this(true);
            }
    
            public AlphabeticalComparator(boolean order)
            {
                this.order = order;
            }
    
            @Override
            public int compare(Object o1, Object o2)
            {
                if (order)
                {
                    return o1.toString().compareTo(o2.toString());
                }
                else
                {
                    return o2.toString().compareTo(o1.toString());
                }
            }
        }
    
        /** Allows sorting according to a pre-defined array
         * 
         */
    
        public static class OrderComparator
        implements Comparator
        {
            private final String[] strings;
    
            public OrderComparator(String[] strings)
            {
                this.strings = strings;
            }
    
            @Override
            public int compare(Object o1, Object o2)
            {
                String s1 = o1.toString();
                String s2 = o2.toString();
                int i1 = -1;
                int i2 = -1;
                for (int j = 0; j < strings.length; j++)
                {
                    if (s1.equals(strings[j]))
                    {
                        i1 = j;
                    }
                    if (s2.equals(strings[j]))
                    {
                        i2 = j;
                    }
                }
                if (i1 == -1 || i2 == -1)
                {
                    throw new Error("Can't use this comparator to compare "+o1+" and "+o2);
                }
                else
                {
                    return Integer.compare(i1,i2);
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-01-13
      • 2011-08-29
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多