【问题标题】:Create JTree using data from text file使用文本文件中的数据创建 JTree
【发布时间】:2013-02-06 07:49:08
【问题描述】:

如何使用.txt 文件中的数据创建JTree?文本文件格式如下:

Root Node
        Category A
            Sub-Category A1
                Item A1.0
                Item A1.1
                Item A1.2
            Sub-Category A2
                Item A2.0
                Item A2.1
                Item A2.2       
        Category B
            Sub-Category B1
                Item B1.0
                Item B1.1
            Sub-Category B2
                Item B2.0
                Item B2.1
            Sub-Category B3
                Item B3.0
                Item B3.1
                Sub-Sub-Category B3_1
                    Item B3_1.0
                    Item B3_1.1
        Category C
            ... etc

.txt 文件包含超过 700 行。

【问题讨论】:

  • @Abhishekkumar;好吧,我知道如何通过逐个添加节点来对 JTree 进行硬编码,但这是一种不好的编程习惯——对实现进行编程而不是对接口进行编程。所以我想要一个更聪明的方法,然后我来到了 StackOverflow,在那里我了解到它不是一个人为你做所有艰苦工作的地方。你挑战我更努力地思考和广泛研究,这让我找到了解决方案。谢谢。

标签: java swing text-files jtree defaulttreemodel


【解决方案1】:

如果 txt 的表格(或空格)格式正确,您可以逐行读取文件,计算空格数,然后根据需要将节点添加到树中。

您可以在java教程How to Use Trees中阅读更多关于JTree的信息。

但正如@Abhishekkumar 所说,您尝试过什么?为什么你做不到?完成你的答案,不要让别人做你的工作。

【讨论】:

  • 谢谢。我实际上在理论上知道该怎么做,但我不知道实现细节。我在网上找不到具体的例子,我想我只是懒得思考并想出实现。
【解决方案2】:

正如PhoenixS在上面的回答中提到的那样,该过程涉及以下步骤:

  1. 逐行读取.txt文件。在此示例中,我们将BufferedReaderInputStreamReaderFileReader 结合使用,具体取决于我们是分别将.txt 文件作为资源读取还是从文件系统读取。
  2. 根据.txt 文件的格式,使用分隔符来确定每行在读取时的层次结构级别。使用它来创建Jtree 的相关节点。在这种情况下,.txt 文件是制表符分隔的,制表符的数量表示层次结构级别。

这是我写的TreeFromTextFile类:

/*
 * File: TreeFromTextFile.java
 * Created 2013-02-06
 * This Class creates a JTree using data from a Specially formatted text File.
 * The supplied text file is tab-delimited, as illustrated at:
 * https://stackoverflow.com/questions/14724014/create-jtree-using-data-from-text-file
 * 
 * You can use either InputStreamReader to read thetext file as a resource
 * or use FileReader to read the text file from the file System
 */


import java.io.BufferedReader;
//import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

/**
 * @author engineervix
 *
 */
public class TreeFromTextFile {

private BufferedReader in;
private LineNumberReader ln;
private String line;    //value of a line in the text file
private String root;    //value to be used for the root Node of our JTree                         
private String filename = "TheTextFile.txt";
private String encoding = "UTF-8";
private DefaultMutableTreeNode top;
private JTree tree;

public TreeFromTextFile() {
    getRootNode();
    top = new DefaultMutableTreeNode(root);
    createNodes(top);

    //Create a tree that allows one selection at a time.
    tree = new JTree(top);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
}

//this method reads the file and prints all the lines to standard output
//for testing purposes
public void readFile() {
    try {
        //in = new BufferedReader(new FileReader("Path\\To\\File.txt"));
        in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename), encoding));

        while ((line = in.readLine()) != null) {
            System.out.println(line);
        }
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

//this method reads the first line in the text file and assigns it 
//to the root variable which will be used for the root node of our JTree
private void getRootNode() {
    try {
        //in = new BufferedReader(new FileReader("Path\\To\\File.txt"));
        in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename), encoding));
        ln = new LineNumberReader(in);

        if (ln.getLineNumber() == 0) {
            root = ln.readLine();
            //System.out.println(root);
        }

        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * this method counts the number of occurrences of a given
 * <code>char</code> in the Specified
 * <code>String</code> source:
 * https://stackoverflow.com/questions/275944/how-do-i-count-the-number-of-occurrences-of-a-char-in-a-string
 */
private int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (int i = 0; i < haystack.length(); i++) {
        if (haystack.charAt(i) == needle) {
            count++;
        }
    }
    return count;
}

//create the Nodes
private void createNodes(DefaultMutableTreeNode top) {
    DefaultMutableTreeNode category = null;     // Level 1 in Hierarchy
    DefaultMutableTreeNode subCategory = null;  // Level 2 in Hierarchy
    DefaultMutableTreeNode leaf = null;         // Level 3 in Hierarchy    

    try {
        //in = new BufferedReader(new FileReader("Path\\To\\File.txt"));
        in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename), encoding));

        while ((line = in.readLine()) != null) {
            if (countOccurrences(line, '\t') == 1) {
                category = new DefaultMutableTreeNode(line);
                top.add(category);
            } else if (countOccurrences(line, '\t') == 2) {
                subCategory = new DefaultMutableTreeNode(line);
                category.add(subCategory);
            } else if (countOccurrences(line, '\t') == 3) {
                leaf = new DefaultMutableTreeNode(line);
                subCategory.add(leaf);
            } //continue the else...if - if you have more levels
        }
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

    public JTree getTree() {
        return tree;
    }
}

为了测试上面的内容,我写了TreeFromTextFileDemo类,如下图:

/*
 * Requires TreeFromTextFile.java
 */

import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;

/**
 * @author engineervix
 */
public class TreeFromTextFileDemo {

private static TreeFromTextFile tr = new TreeFromTextFile();

public static void main(String[] args) {
    JFrame frame = new JFrame("Demo | Creating JTree From File.txt");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = frame.getContentPane();

    JTree t = tr.getTree();

    content.add(new JScrollPane(t), BorderLayout.CENTER);
    frame.setSize(275, 300);
    frame.setLocationByPlatform(true);
    frame.setVisible(true);

    }
}

以下屏幕截图说明了输出。您可以使用this file 作为示例文本文件。

【讨论】:

    【解决方案3】:

    如果您希望它更灵活,请不要对关卡进行硬编码。只需使用 Map 将最后一个节点保留在任何给定级别。当您遍历文件中的项目时,您将可以通过地图访问任何父节点。这是代码...

    public class StructureBuilder {
    
        public static final DefaultMutableTreeNode getTreeNode(File file) throws IOException  {
    
            DefaultMutableTreeNode rootNode = null;
            Map<Integer, DefaultMutableTreeNode> levelNodes = new HashMap<Integer, DefaultMutableTreeNode>();
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String line;
    
            while( (line = reader.readLine()) != null ) {
    
                int level = getLevel(line);
                String nodeName = getNodeName(line, level);
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(nodeName);               
                levelNodes.put(level, node);
                DefaultMutableTreeNode parent = levelNodes.get(level - 1);
    
                if( parent != null ) {
                    parent.add(node);
                }
                else {
                    rootNode = node;
                }
            }    
            reader.close();
            return rootNode;
        }
    
        private static final int getLevel(String line) {
    
            int level = 0;
            for ( int i = 0; i < line.length(); i++ ) {
                char c = line.charAt(i);
                if( c == '\t') {
                    level++;
                }
                else {
                    break;
                }
            }
            return level;
        }
    
        private static final String getNodeName(String line, int level) {
            return line.substring(level);
        }      
    }
    

    【讨论】:

      【解决方案4】:

      我遇到了类似的问题,为此编写了一个通用的构建器类。它需要我们的源数据集合和层次结构描述和宾果游戏。树模型。

      您还可以实时交换结构。

      https://stackoverflow.com/a/29823595/4824123

      项目:https://github.com/mnrussell/collectionTreeModel

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        • 2021-10-05
        相关资源
        最近更新 更多