adjust selected File to FileFilter in a JFileChooser

You can also use a PropertyChangeListener on the SELECTED_FILE_CHANGED_PROPERTY prior to attaching your suffix. When the selected file gets checked against the new filter (and subsequently set to null), the SELECTED_FILE_CHANGED_PROPERTY event is actually fired before the FILE_FILTER_CHANGED_PROPERTY event.

If the evt.getOldValue() != null and the evt.getNewValue() == null, you know that the JFileChooser has blasted your file. You can then grab the old file's name (using ((File)evt.getOldValue()).getName() as described above), pull off the extension using standard string parsing functions, and stash it into a named member variable within your class.

That way, when the FILE_FILTER_CHANGED event is triggered (immediately afterwards, as near as I can determine), you can pull that stashed root name from the named member variable, apply the extension for the new file filter type, and set the JFileChooser's selected file accordingly.


Here is my solution and it works fine. It maybe helps someone. You sould create your own "MyExtensionFileFilter" class, otherwise you have to modify the code.

public class MyFileChooser extends JFileChooser {
    private File file = new File("");

    public MyFileChooser() {
        addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String filename = MyFileChooser.this.file.getName();
                String extold = null;
                String extnew = null;
                if (e.getOldValue() == null || !(e.getOldValue() instanceof MyExtensionFileFilter)) {
                    return;
                }
                if (e.getNewValue() == null || !(e.getNewValue() instanceof MyExtensionFileFilter)) {
                    return;
                }
                MyExtensionFileFilter oldValue = ((MyExtensionFileFilter) e.getOldValue());
                MyExtensionFileFilter newValue = ((MyExtensionFileFilter) e.getNewValue());
                extold = oldValue.getExtension();
                extnew = newValue.getExtension();

                if (filename.endsWith(extold)) {
                    filename = filename.replace(extold, extnew);
                } else {
                    filename += ("." + extnew);
                }
                setSelectedFile(new File(filename));
            }
        });
    }

    @Override
    public void setSelectedFile(File file) {
        super.setSelectedFile(file);
        if(getDialogType() == SAVE_DIALOG) {
            if(file != null) {
                super.setSelectedFile(file);
                this.file = file;
            }
        }
    }

    @Override
    public void approveSelection() { 
        if(getDialogType() == SAVE_DIALOG) {
            File f = getSelectedFile();  
            if (f.exists()) {  
                String msg = "File existes ...";  
                msg = MessageFormat.format(msg, new Object[] { f.getName() });  
                int option = JOptionPane.showConfirmDialog(this, msg, "", JOptionPane.YES_NO_OPTION);
                if (option == JOptionPane.NO_OPTION ) {  
                    return;  
                }
            }
        }
        super.approveSelection();   
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if(!visible) {
            resetChoosableFileFilters();
        }
    }
}

It looks like you can listen to the JFileChooser for a change on the FILE_FILTER_CHANGED_PROPERTY property, then change the extension of the selected file appropriately using setSelectedFile().


EDIT: You're right, this solution doesn't work. It turns out that when the file filter is changed, the selected file is removed if its file type doesn't match the new filter. That's why you're getting the null when you try to getSelectedFile().

Have you considered adding the extension later? When I am writing a JFileChooser, I usually add the extension after the user has chosen a file to use and clicked "Save":

if (result == JFileChooser.APPROVE_OPTION)
{
  File file = fileChooser.getSelectedFile();
  String path = file.getAbsolutePath();

  String extension = getExtensionForFilter(fileChooser.getFileFilter());

  if(!path.endsWith(extension))
  {
    file = new File(path + extension);
  }
}

fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener()
{
  public void propertyChange(PropertyChangeEvent evt)
  {
    FileFilter filter = (FileFilter)evt.getNewValue();

    String extension = getExtensionForFilter(filter); //write this method or some equivalent

    File selectedFile = fileChooser.getSelectedFile();
    String path = selectedFile.getAbsolutePath();
    path.substring(0, path.lastIndexOf("."));

    fileChooser.setSelectedFile(new File(path + extension));
  }
});

How about this:

class MyFileChooser extends JFileChooser {
   public void setFileFilter(FileFilter filter) {

    super.setFileFilter(filter);

    FileChooserUI ui = getUI();

    if( ui instanceof BasicFileChooserUI ) {
     BasicFileChooserUI bui = (BasicFileChooserUI) ui;

     String file = bui.getFileName();

     if( file != null ) {
      String newFileName = ... change extension 
      bui.setFileName( newFileName );
     }
    }
   }
  }