【问题标题】:JTree - how can i stop children from showing relative path?JTree - 我怎样才能阻止孩子显示相对路径?
【发布时间】:2014-08-01 01:51:59
【问题描述】:

在我们开始之前,我想指出我对 JTree 及其亲属比较陌生。

我节点中的子节点显示返回其父节点的相对路径,但我不希望它这样做。

这是它的样子

http://puu.sh/azCJa/8dd84029b7.png

我希望它是这样的:

testing 0
>testing 1
>>file 1

不是

testing 0
>testing 0\testing 1
>>...

这是一些可运行的代码。

import java.awt.Color;
import java.io.File;
import java.util.Collections;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

public class NGui {

    JFrame frame;
    private JTree tree;

    public NGui() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setResizable(false);
        frame.setBounds(100, 100, 493, 608);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 11, 212, 500);
        frame.getContentPane().add(scrollPane);

        tree = new JTree(addNodes(null, new File(getWorkPath())));
        tree.setRootVisible(false);
        tree.setShowsRootHandles(true);

        tree.setBorder(new LineBorder(new Color(0, 0, 0)));
        tree.getSelectionModel().setSelectionMode(
                TreeSelectionModel.SINGLE_TREE_SELECTION);
        scrollPane.setViewportView(tree);

        tree.getSelectionModel().addTreeSelectionListener(
                new TreeSelectionListener() {
                    @Override
                    public void valueChanged(TreeSelectionEvent e) {
                        treeValueChanged(e);
                    }
                });
    }

    private String getWorkPath() {
        return System.getProperty("user.home") + "\\Program Name\\";
    }

    private void treeValueChanged(TreeSelectionEvent e) {
    }

    DefaultMutableTreeNode addNodes(DefaultMutableTreeNode top, File dir) {
        String curPath = dir.getPath();
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(
                curPath.replace(getWorkPath(), ""));
        if (top != null) { // should only be null at root
            log("Adding curPath: " + root);
            top.add(root);
        }
        Vector<String> ol = new Vector<String>();
        String[] tmp = dir.list();
        for (String s : tmp) {
            log("Adding file: " + s);
            ol.addElement(s);
        }
        Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
        File file;
        Vector<String> files = new Vector<String>();
        // for dirs
        for (int i = 0; i < ol.size(); i++) {
            String filePath = ol.elementAt(i);
            String newPath;

            if (curPath.equals(".")) // if root
                newPath = filePath;
            else
                // not root
                newPath = curPath + File.separator + filePath;
            file = new File(newPath);
            log(String.format("cur: %s | file: %s | new: %s", curPath,
                    filePath, newPath));
            // if not a file then go inside folder and get files
            if (file.isDirectory())
                addNodes(root, file);
            else if (filePath.contains(".txt")) // txt files only
                files.addElement(filePath);

        }
        // for files
        for (int fnum = 0; fnum < files.size(); fnum++)
            root.add(new DefaultMutableTreeNode(files.elementAt(fnum).replace(getWorkPath(), ""), true));
        return root;
    }

    public void log(Object o) {
        System.out.println(o);
    }
}

【问题讨论】:

  • 考虑提供一个runnable example 来证明您的问题。这将导致更少的混乱和更好的响应
  • 我会更仔细、非常仔细地查看newPath = curPath + File.separator + filePath。在代码中的这一点添加断点并启动 IDE 的调试器并检查此值的结果并查看您发现的内容...
  • 我已经看过了,但仍然不太明白问题所在。更改那里的任何内容都会导致 StackOverflow 或停止列出节点中的子节点。为问题添加一个可运行的示例

标签: java swing jtree treenode


【解决方案1】:

问题的原因在这里...

if (curPath.equals(".")) // if root
    newPath = filePath;
else
    // not root
    newPath = curPath + File.separator + filePath;

基本上,它的意思是,除非您是根节点,否则将 curPath(即 dir.getPath())前缀到 filePath...这就是为什么您会在树中获得 path/path...

整个if 声明毫无意义,根据您想要实现的目标并完全替换为...

newPath = filePath;

面对,你可以去掉newPath,直接使用filePath...

更新

您的核心设计根本无法实现您想要实现的目标......

尝试维护路径信息作为Strings 过于复杂且容易出错,维护File 引用要简单得多,它为您提供呈现文件名和访问文件所需的所有信息用于其他目的...适合工作的工具...

一些背景,JTree 使用的默认TreeCellRenderer 只是使用TreeModel 中对象的toString 方法将某些内容渲染到UI。在DefaultMutableTreeNode 的情况下,这只是使用您传递的userData 对象的toString 方法,所以这意味着,当您执行curPath.replace(getWorkPath(), "") 时,这最终会出现在屏幕上,但不是你想要什么。

相反,您应该将实际的File 传递给DefaultMutableTreeNode,并使用自定义TreeCellRenderer 来修改进入屏幕的值,例如...

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.io.File;
import java.util.Collections;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;

public class NGui {

    JFrame frame;
    private JTree tree;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                new NGui();
            }
        });
    }

    public NGui() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 11, 212, 500);
        frame.getContentPane().add(scrollPane);

        tree = new JTree(addNodes(new File(getWorkPath())));
        tree.setRootVisible(false);
        tree.setShowsRootHandles(true);

        tree.setBorder(new LineBorder(new Color(0, 0, 0)));
        tree.getSelectionModel().setSelectionMode(
                TreeSelectionModel.SINGLE_TREE_SELECTION);
        scrollPane.setViewportView(tree);

        tree.getSelectionModel().addTreeSelectionListener(
                new TreeSelectionListener() {
                    @Override
                    public void valueChanged(TreeSelectionEvent e) {
                        treeValueChanged(e);
                    }
                });
        tree.setCellRenderer(new FileTreeCellRenderer());

        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private String getWorkPath() {
//        return System.getProperty("user.home") + "\\Program Name\\";
        return ".";
    }

    private void treeValueChanged(TreeSelectionEvent e) {
    }

    public DefaultMutableTreeNode addNodes(File dir) {
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                node.add(addNodes(file));
            } else {
                node.add(new DefaultMutableTreeNode(file));
            }
        }
        return node;
    }

    public class FileTreeCellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof DefaultMutableTreeNode) {
                value = ((DefaultMutableTreeNode)value).getUserObject();
                if (value instanceof File) {
                    value = ((File) value).getName();
                }
            }
            return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        }

    }

}

查看Customizing a Tree's Display了解更多详情

【讨论】:

  • curPath 是文件夹的路径 filePath 是文件/文件夹本身 你的建议不起作用,除非我做错了。
  • 但是你不需要它来显示,DefaultTreeNode 只需要filePath 值...事实上,我会停止使用String 并改用File,但这需要提供TreeCellRenderer
  • 我需要文件的绝对路径,因为我正在预览和修改选定的文件,这就是我这样做的原因。
  • 这似乎比我做的要容易得多。谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-26
  • 2021-09-27
  • 2020-03-30
  • 2013-02-28
  • 2021-06-15
  • 1970-01-01
  • 2021-12-30
相关资源
最近更新 更多