Java JFileChooser在键入时按名称筛选文件
我已经知道了如何按文件类型过滤,但当我在键盘上的文件名文本字段中键入时,我无法知道如何过滤文件。如果我的目录中有1000个文件,其中两个文件以字母q开头,那么我希望当我在myJava JFileChooser在键入时按名称筛选文件,java,swing,user-interface,filter,jfilechooser,Java,Swing,User Interface,Filter,Jfilechooser,我已经知道了如何按文件类型过滤,但当我在键盘上的文件名文本字段中键入时,我无法知道如何过滤文件。如果我的目录中有1000个文件,其中两个文件以字母q开头,那么我希望当我在myJFileChooser中键入单词q时,它会过滤掉所有不以q开头的文件,并且在我键入时应继续此操作,并应选择最佳匹配项。没有这方面的范例吗?似乎每个JFileChooser问题和教程都只关注按文件类型过滤,而不是按名称过滤。我认为为JFileChooser实现全面自动完成可能不是一件小事。您需要访问选择器的JTextFiel
JFileChooser
中键入单词q时,它会过滤掉所有不以q开头的文件,并且在我键入时应继续此操作,并应选择最佳匹配项。没有这方面的范例吗?似乎每个JFileChooser
问题和教程都只关注按文件类型过滤,而不是按名称过滤。我认为为JFileChooser
实现全面自动完成可能不是一件小事。您需要访问选择器的JTextField,但这并不容易(尽管并非不可能)。然后,您可以对该字段应用自定义DocumentFilter,然后根据用户类型自动填充(并部分选择单词的后端)
进一步阅读:
然而,这似乎需要做很多工作
相反,您是否知道JFileChooser允许您动态创建过滤器?只需调出选择器,输入'q*”
,点击回车键,选择器将只显示以“q”开头的文件。这适用于金属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
- 我只为文件设置了过滤器。如果要将此应用于目录,请更改
的FileFilter
方法accept
- 筛选器区分大小写,因为它当前已实现。您可以通过更改
的FileFilter
方法来修改此行为accept
- 我添加了空帧,以便JVM在您关闭它时退出(作为对话框的文件选择器不会这样做)
- 根据大图,根据需要设置字段和方法的修饰符
- 我现在有了我想要的行为。我仍然无法相信这是一场多么艰难的斗争,但我想Swing社区中没有人认为让JFileChooser拥有这种行为或者有更好的钩子来实现它是合适的。感谢用户1803551的回答,我接受了你的回答,我发布了我的答案,只是为了展示我如何调整你的答案,以获得我想要的行为
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;
}
});
}
}
类似于?这篇文章来自2001年,声称在1.4中JFileChooser有一个内置的提前类型选择器。我没能找到这个。我对这篇文章也有很多问题。首先,“findJList”方法很粗糙。其次,没有完整的代码示例。第三点也是最后一点,当您键入时从视图中筛选出文件的行为没有得到解决。在现代Java中,必须有一种更优雅的方式来实现这种行为。您是否知道,如果您选择一个文件并键入一个字母序列,它会为您导航到以该序列开头的文件?您要修改的文本字段是
MetalFileChooserUI
中的私有字段(假设为Metal-LAF)。这里没有太多选项-从UI类复制粘贴代码或遍历文件选择器。您刚才用*描述的行为非常有效。我想让这种行为在每次击键时都发生,而不仅仅限于添加*和按enter键。可能吗?我对全尺寸自动完成不感兴趣。我想在键入时进行筛选。我对全刻度自动完成不感兴趣。我想在键入时进行筛选。
我看不出有什么区别。你能解释一下吗?我想在键入时进行筛选自动完成对我来说,但这些功能在默认情况下使用startWith,而不是contains,不可能是,我认为没有问题,但正如@splungebob所描述的那样并不容易,而且在我键入时需要effortBy过滤器。我的意思是,如果我在下面的JTextField中点击“f”,那么上面JList中的所有文件都应该消失,除非它们以“f”开头。我不希望JTextField自动完成以“f”开头的第一个文件,这是自动完成。我的意思清楚了吗?这很有效!但是我有一个问题,如果我点击一个文件,然后在一个目录上远离它,然后再次点击该文件,文件选择器中的选择就会消失。我不明白为什么会发生这种事……嗯。。。对第一次选择文件时也会发生这种情况。发生的情况是,无论何时更改过滤器,文件和文件夹列表都会刷新,并且您将丢失当前选择。它实际上也发生在你打字的时候,但在这种情况下你不会注意到它。如果您愿意,可以使选择文件不会自动将其名称放入字段。设置新过滤器后,我们尝试重新选择文件,列表会刷新,但这并不容易。由于某种原因,invokeLater
无法在此处执行此任务。我们可以采取一些不顾一切的措施,你认为呢?既然你在KeyListener
中只实现了一个方法,你最好使用KeyAdapter
。此外,不确定为什么需要检查文本是否等于“”,空字符串会自动工作;您在第二个if
中缺少了一个返回true
。此外,我认为需要将KeyListener添加到JTextField,而不是选择器