JFileChooser在您键入时按名称过滤文件

时间:2014-05-05 21:06:17

标签: java swing user-interface filter jfilechooser

我已经想出了如何按文件类型进行过滤,但是当我在文件名文本字段中键入键盘时,我无法弄清楚如何过滤掉文件。如果我的目录中有1000个文件,其中两个以字母 q 开头,那么我希望当我在JFileChooser中输入单词 q 时它会过滤掉所有不以 q 开头的文件,这应该在我输入时继续,并且应该选择最佳匹配。这个没有例子吗?似乎每个JFileChooser问题和教程只关注按文件类型而不是按名称进行过滤。

3 个答案:

答案 0 :(得分:1)

我认为为JFileChooser实施全面自动完成可能并非易事。您需要访问选择器的JTextField,但这并不容易获得(尽管并非不可能)。然后,您可以将自定义DocumentFilter应用于该字段,然后在用户键入时自动填充(并部分选择单词的后端)。

进一步阅读: http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter

然而,这似乎是很多工作。

相反,您是否意识到JFileChooser允许您即时创建过滤器?只需调出选择器,输入'q*',然后按ENTER键,选择器将只显示以'q'开头的文件。

答案 1 :(得分:1)

这适用于(对于Metal LAF)。虽然这本身就是一个可怕的解决方案,但其他选择并不是更令人开胃。

public class FilterChooser {

    JFileChooser chooser = new JFileChooser();
    JTextField tf = (JTextField) ((JPanel) ((JPanel) chooser.getComponent(3)).getComponent(0)).getComponent(1);

    FilterChooser() {

        tf.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {

                modifyFilter();
            }

            public void removeUpdate(DocumentEvent e) {

                modifyFilter();
            }

            public void changedUpdate(DocumentEvent e) {

                modifyFilter();
            }
        });

        JFrame f = new JFrame();
        chooser.showOpenDialog(f);

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

    void modifyFilter() {

        final String text = tf.getText();
        chooser.setFileFilter(new FileFilter() {

            @Override
            public String getDescription() {

                return null;
            }

            @Override
            public boolean accept(File f) {

                return (f.isDirectory() || f.getName().startsWith(text));
            }
        });
    }

    public static void main(String[] args) {

        new FilterChooser();
    }
}

注释和解释:

  • JFileChooser中的文本字段在MetalFileChooserUI类中声明为private字段,因此无法轻松到达它。我按照我的方式将其取入tf,因为我完成了我的作业并检查了它的位置 - 如果布局发生变化(由于向后兼容性将在未来几年内不会发生),这个会< / em>休息。您也可以递归地遍历子组件。
  • 我只为文件设置过滤器。如果要将其应用于目录,请更改accept。{/ li>的FileFilter方法
  • 过滤器区分大小写,因为它目前已实现。您可以通过更改accept。{/ li>的FileFilter方法来修改此行为
  • 我添加了空帧,因此JVM将在您关闭它时退出(文件选择器,作为对话框,不执行此操作)。
  • 根据更大的图片,根据需要设置字段和方法的修饰符。

答案 2 :(得分:0)

我现在有我想要的行为。我仍然无法相信这是多么艰难,但我想Swing社区中没有人认为让JFileChooser有这种行为或者有更好的钩子来实现它是合适的。感谢您对user1803551的回答,我接受了您的回答,我发布了我的内容,以表明我是如何调整您的,以获得我所期望的行为。

public void setupListeners()
{
    JFileChooser chooser = new JFileChooser();
    JTextField fileChooserTextField = (JTextField) ((JPanel) ((JPanel) chooser.getComponent(3)).getComponent(0)).getComponent(1);

    chooser.addKeyListener(new KeyListener()
    {
       @Override
       public void keyTyped(KeyEvent e)
       {
       }
       @Override
       public void keyReleased(KeyEvent e)
       {
          filterAsYouType(fileChooserTextField, chooser);
       }
       @Override
       public void keyPressed(KeyEvent e)
       {
       }
    });
}

    private void filterAsYouType(final JTextField tf, final JFileChooser chooser)
    {
    final String text = tf.getText();
    chooser.setFileFilter(new FileFilter()
    {
       @Override
       public boolean accept(File f)
       {
          if(text.equals("")
          {
             return true;
          }
          if(f.getName().equals(text))
          {
             chooser.setSelectedFile(f);
             tf.setCaretPosition(text.length());
          }
          if(f.getName().startsWith(text))
          {
             return true;
          }
          return false;
       }
       @Override
       public String getDescription()
       {
          return null;
       }
    });
    }
}