This works (for Metal LAF). Although it is a terrible solution in itself, the other options are not more appetizing.
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();
}
}
Notes and explanations:
- The text field in a JFileChooser is declared in the
MetalFileChooserUI
class as aprivate
field, hence no easy way to reach it. I fetch it intotf
the way I do because I did my homework and checked where it is located - if the layout changes (won't happen in the next many years due to backwards compatibility) this will break. You can alternatively recursively iterate through child components. - I set the filter for files only. If you want this to apply to directories, change the
accept
method of theFileFilter
. - The filter is case-sensitive as it is currently implemented. You can modify this behavior by changing the
accept
method of theFileFilter
. - I added the empty frame just so the JVM will exit when you close it (the file chooser, being a dialog, does not do this).
- Depending on the bigger picture, set the modifiers of the fields and methods to your needs.