简体   繁体   中英

Changing selected files in a JFileChooser in response to an event

I would like my JFileChooser to allow multiple file selection, but with a limit on the number of files that can be selected simultaneously.

Ideally I would like to constrain the selection in real-time, with priority given to the most-recently selected file, ie when a 3rd file is selected, the 1st file (ie the one that was selected earliest) should be deselected automatically.

I thought that a PropertyChangeListener like this one would work:

public static void main(String[] args) throws IOException {
    final JFileChooser fc = new JFileChooser(didir);
    fc.setMultiSelectionEnabled(true);
    fc.addPropertyChangeListener(new PropertyChangeListener() {
        private final Set<File> selected = Sets.newLinkedHashSet();
        public void propertyChange(PropertyChangeEvent evt) {
            if (JFileChooser.SELECTED_FILES_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                File[] selectedFiles = fc.getSelectedFiles();
                if (selectedFiles.length > 2) {
                    selected.addAll(Arrays.asList(selectedFiles));
                    int numToRemove = Math.max(0, selected.size() - 2);
                    Iterables.removeIf(Iterables.limit(selected, numToRemove),
                                       Predicates.alwaysTrue());
                    fc.setSelectedFiles(selected.toArray(new File[0]));
                }
            }
        }
    });
    fc.showOpenDialog(null);
}

However the call to fc.setSelectedFiles() has no effect (although it fires an event, it does not update the selection in the list.)

Is there any way to programatically force a change to the selection while the JFileChooser is open? Or is there another way to limit the size of the selection?

I have discovered that this bug is specific to the Macintosh look-and feel. setSelectedFile and setSelectedFiles do not work at all on the Mac (even before the dialog is opened.) My sample code works fine with the Metal look-and-feel.

Possible workarounds include:

  • Use a different look-and-feel
  • Use a FileDialog instead of a JFileChooser (does not support multiple file selection)
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;

public class MyClass {
    final static JFileChooser fc = new JFileChooser("/");
    public static void main(String[] args) throws IOException {
        fc.setMultiSelectionEnabled(true);
        fc.addPropertyChangeListener(new ChangeListener());
        fc.showOpenDialog(null);
    }

    private static class ChangeListener implements PropertyChangeListener{
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (JFileChooser.SELECTED_FILES_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                File[] selectedFiles = fc.getSelectedFiles();
                File[] allowedFiles = new File[2];
                if (selectedFiles.length > 2) {
                    allowedFiles[0] = selectedFiles[1];
                    allowedFiles[1] = selectedFiles[0];

                        fc.setSelectedFiles(allowedFiles);
                }
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM