我已经弄清楚如何按文件类型过滤,但我无法弄清楚如何过滤掉文件,因为我在键盘上键入文件名文本字段。如果我的目录中有1000个文件,其中两个以字母q开头,那么我希望当我在JFileChooser
中键入q这个词时,它将过滤掉所有不以q开头的文件,并且在我键入时应该继续,并且应该选择最佳匹配。难道就没有这样的例子吗?似乎每个JFileChooser
问题和教程都只关注按文件类型过滤,而不是按名称过滤。
这行得通(对于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
中,因为我做了功课,检查了它的位置——如果布局改变了(由于向后兼容性,在未来几年不会发生),这个将中断。你也可以递归地迭代子组件。 - 我只对文件设置过滤器。如果你想把它应用到目录,改变
FileFilter
的accept
方法。 - 过滤器是区分大小写的,因为它是目前实现的。您可以通过更改
FileFilter
的accept
方法来修改此行为。 - 我添加了空框架,这样JVM就会在你关闭它时退出(文件选择器,作为一个对话框,不会这样做)。
- 根据更大的画面,设置字段和方法的修饰符以满足您的需要。
我认为为JFileChooser
实现全面自动完成可能不是一件小事。您需要访问选择器的JTextField,但这不是现成的(尽管并非不可能)。然后,您可以将自定义DocumentFilter应用于该字段,然后自动填充(并部分选择单词的后端)作为用户类型。
进一步阅读:http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html过滤器
然而,这似乎是很多工作。
相反,您知道JFileChooser允许您动态创建过滤器吗?打开选择器,输入'q*'
,按回车键,选择器将只显示以'q'开头的文件。
我现在有我想要的行为。我仍然无法相信这是一场多么大的斗争,但我猜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;
}
});
}
}