Reputation: 10323
I have figured out how to filter by file-type, but I cannot figure out how to filter out files as I type on my keyboard in the file-name textfield. If I have 1000 files in my directory and two of them start with the letter q then I expect that when I type the word q in my JFileChooser
it will filter out all files that do not start with q and this should continue as I type and the best possible match should be selected. Is there no exemplar for this? It seems like every JFileChooser
question and tutorial out there is only concerned with filtering by file-type and not by name.
Upvotes: 2
Views: 1353
Reputation: 10323
I have the behavior that I want now. I still cannot believe what a struggle this was, but I guess nobody in the Swing community ever saw it fit to have the JFileChooser have this behavior or have better hooks for implementing it. Thank you user1803551 for your answer, I am accepting your answer and I posted mine just to show how I tweaked yours to get my exact desired behavior.
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;
}
});
}
}
Upvotes: 0
Reputation: 13407
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:
MetalFileChooserUI
class as a private
field, hence no easy way to reach it. I fetch it into tf
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.accept
method of the FileFilter
.accept
method of the FileFilter
.Upvotes: 1
Reputation: 5415
I imagine that implementing a full-scale auto-complete for a JFileChooser
might not be trivial. You would need access to the JTextField of the chooser, but that isn't readily available (though not impossible). You could then apply a custom DocumentFilter to that field, and then auto-populate (and partial select the back end of the word) as the user types.
Further reading: http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter
However, that seems like a lot of work.
Instead, are you aware that JFileChooser allows you to create a filter on-the-fly? Just bring up the chooser, type in 'q*'
, hit ENTER, and the chooser will show only the files that begin with 'q'.
Upvotes: 1