简体   繁体   English

根据JTextField的输入过滤JTree中的结果

[英]Filter results in JTree based on input from JTextField

Here is the run down on my program 这是我程序的失败

Lists all folders, subfolders, and files of X extension from a specified directory. 列出指定目录中X扩展名的所有文件夹,子文件夹和文件。 You can view, edit, copy, etc the contents of the files. 您可以查看,编辑,复制等文件的内容。 Each file has a .dat file associated with it that contains information such as keywords and last use date. 每个文件都有一个与其相关联的.dat文件,其中包含诸如关键字和最后使用日期之类的信息。

Right now I'm creating a filter. 现在,我正在创建一个过滤器。 The way it should filter is take the inputted text and return any folders and files with the filter in its name, files which keywords contain and files which contents contain. 过滤方式是采用输入的文本并返回名称中带有过滤器的所有文件夹和文件,关键字包含的文件以及内容包含的文件。

Easy enough, right? 很容易,对吧?

My only problem is that it will do one of the following (based on location of File ) 我唯一的问题是它将执行以下一项操作(基于File位置)

if folder matches
-> only lists to that folder, but not contents

if file matches
-> only lists file if its in JTree root

if file matches but is in a folder which doesnt match
-> doesnt display

I apologize if that is hard to understand. 如果这很难理解,我深表歉意。 Below is functional code, copied and cleaned up from my real program. 下面是功能代码,它们是从我的真实程序中复制并清除的。 Uses apache commons 2.4 使用Apache Commons 2.4

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
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.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;

import org.apache.commons.io.FileUtils;

public class NGui {

    JFrame frame;
    private JTree tree;
    private JTextField jtf;

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

    public NGui() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.getContentPane().setLayout(null);
        frame.setSize(250, 400);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 50, 200, 300);
        frame.getContentPane().add(scrollPane);

        tree = new JTree(addNodes(new File(getWorkPath())));
        tree.setRootVisible(true);
        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());

        jtf = new JTextField();
        jtf.setBorder(new LineBorder(new Color(0, 0, 0)));
        jtf.setBounds(10, 10, 150, 25);
        Object actionKey = jtf.getInputMap(JComponent.WHEN_FOCUSED).get(
                KeyStroke.getKeyStroke("ENTER"));
        jtf.getActionMap().put(actionKey, new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    filterResults(ae);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        frame.getContentPane().add(jtf);

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

    private void treeValueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
                .getLastSelectedPathComponent();
        log("Selected Node: " + node);
    }

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

    private String getWorkPath() {
        return ".";
    }

    public void filterResults(ActionEvent ae) throws Exception {

        final String str = jtf.getText();
        reloadTree("."); // refreshes from any previous searches

        DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel()
                .getRoot();

        reloadTree(root.toString(), str);
    }

    public DefaultMutableTreeNode addNodes(File dir, String filter)
            throws Exception {
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
        for (File file : dir.listFiles()) {

            if (file.isDirectory()) {
                if (file.getPath().contains(filter)) {
                    log("adding: " + file.toString());
                    node.add(addNodes(file));
                }
            } else {
                // apache commons 2.4
                String tmpContent = FileUtils.readFileToString(file);
                if (file.getPath().contains(filter)
                        || tmpContent.contains(filter)) {
                    log("adding: " + file.toString());
                    node.add(new DefaultMutableTreeNode(file));
                }

            }
        }
        return node;
    }

    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 void reloadTree(final String path) {
        DefaultMutableTreeNode dn = addNodes(new File(path));
        tree.setModel(new DefaultTreeModel(dn));
    }

    public void reloadTree(final String path, final String filter)
            throws Exception {
        DefaultMutableTreeNode dn = addNodes(new File(path), filter);
        tree.setModel(new DefaultTreeModel(dn));
    }

    public class FileTreeCellRenderer extends DefaultTreeCellRenderer {
        private static final long serialVersionUID = 1L;
        @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);
        }
    }

}

The problem lies in the filtering algorithm. 问题在于过滤算法。

  1. You missed out to call the filter on the subcomponents again (instead of addNodes(file) you have to call addNodes(file, filter)). 您错过了再次调用子组件上的过滤器的方法(而不是必须调用addNodes(file)来代替addNodes(file))。

  2. Directory nodes where only added if they match, not if subcomponents match. 目录节点仅在它们匹配时才添加,而在子组件匹配时则不添加。

A quick hack to make your code working looks like this (replace the addNodes method): 使您的代码正常工作的快速技巧如下(替换addNodes方法):

public DefaultMutableTreeNode addNodes(File dir, String filter)
        throws Exception {
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
    //true iff any subcomponent matches
    boolean matchFound = false;
    for (File file : dir.listFiles()) {

        if (file.isDirectory()) {
            if (file.getName().contains(filter)) {
                matchFound = true;
            } 
            //always call addNodes on directories, because subcomponents may match
            //null return value indicates no match (with Java 8 use Optional for this)
            DefaultMutableTreeNode maybeNode = addNodes(file, filter);
            if(maybeNode != null) {
                matchFound = true;
                node.add(maybeNode);
            }
        } else {
            // apache commons 2.4
            String tmpContent = FileUtils.readFileToString(file);
            if (file.getName().contains(filter)
                    || tmpContent.contains(filter)) {
                matchFound = true;
                log("adding file: " + file.toString());
                node.add(new DefaultMutableTreeNode(file));
            }
        }
    }
    //only return node if node itself or subcomponent matches
    if(matchFound || dir.getName().contains(filter)) {
        return node;
    }
    //return null otherwise
    return null;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM