JFileChooser按照单击的顺序打开多个文件

时间:2015-03-26 17:14:47

标签: java swing jfilechooser look-and-feel

我有一个应用程序,它接受多个文件并应用一些取决于它们的顺序的操作(例如,一个接一个地合并它们)。

用户可以通过Ctrl +单击或Shift +单击按任意顺序选择文件。

选择器返回的列表文件与用户单击它们的顺序不同。我希望它们以用户点击它们的相同顺序返回。

免责声明:我是“用户”

我在Windows 7 64位上使用带有Java外观的JFileChooser类,使用JDK 7.

这是一个最小的例子

package choosertest;

import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

public class ChooserTest extends JFrame {

    JFileChooser chooser;

    public ChooserTest() {
        chooser = new JFileChooser();
        chooser.setMultiSelectionEnabled(true);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        testOpen();
    }

    public static void main(String[] args) {
        new ChooserTest();
    }

    private void testOpen() {
        int choice = chooser.showOpenDialog(this);

        if (choice == JFileChooser.APPROVE_OPTION) {

            File[] inputFiles = chooser.getSelectedFiles();
            for (File f: inputFiles) {
                System.out.println(f.getName());
            }
        }
    }

}

3 个答案:

答案 0 :(得分:1)

您可以考虑在选择后使用类似JTable / JList的方式重新排序文件,而不是根据JFileChooser中的选择顺序对文件进行排序。尽管如此,您可以通过向JFileChooser添加PropertyChangeListener来插入JFileChooser的侦听器系统以获取选择顺序。每当选择一个文件时,' SelectedFilesChangedProperty'被触发,PropertyChangeEvent.getNewValue()应返回所选文件

    final JFileChooser chooser = new JFileChooser();
    chooser.setMultiSelectionEnabled(true);
    chooser.addPropertyChangeListener(new PropertyChangeListener(){

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if ( evt.getPropertyName().equals("SelectedFilesChangedProperty") ){
                System.out.println(Arrays.toString((File[])evt.getNewValue()));
            }
        }
    });

您需要检查getNewValue()返回的Files数组,以查看选择(或取消选择)哪个新文件以维持顺序。

答案 1 :(得分:0)

我说到Ctrl +点击工作,Shift +点击选择文件"向下"的工作原理。

然而,使用Shift +单击选择文件"向上"仍然以错误的顺序添加文件,这可能令人困惑。

此外,此解决方案不会更新"文件名"文本字段以反映选择的实际顺序。有可能"修复"但是,这可以使用反射。

File name text field

如果您需要一个快速解决方案,通过按住Ctrl键单击它们以正确的顺序选择文件,这可以正常工作(选择和取消选择)。

package choosertest;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

public class ChooserTest extends JFrame {

    File[] selected;
    JFileChooser chooser;

    public ChooserTest() {
        chooser = new JFileChooser();
        chooser.setMultiSelectionEnabled(true);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        testOpen();
    }

    public static void main(String[] args) {
        new ChooserTest();
    }

    private void testOpen() {

        chooser.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals("SelectedFilesChangedProperty")) {
                    if (selected == null) {
                        selected = (File[]) evt.getNewValue();
                    } else {
                        File[] newSelection = (File[]) evt.getNewValue();

                        if (newSelection == null) {
                            selected = null;
                        }
                        // check back and forth to preserve the order of files
                        // as the user added them
                        else {
                            List<File> orderedSel = new LinkedList<>();

                            // add files that are still selected
                            for (File f : selected) {
                                for (File f2 : newSelection) {
                                    if (f.equals(f2)) {
                                        orderedSel.add(f);
                                        break;
                                    }
                                }
                            }

                            Arrays.sort(selected);
                            // add newly selected files
                            for (File f : newSelection) {
                                if (Arrays.binarySearch(selected, f) < 0) {
                                    orderedSel.add(f);
                                }
                            }

                            selected = orderedSel.toArray(
                                    new File[orderedSel.size()]);
                        }
                    }
                    System.out.println(Arrays.toString(selected)); //debug
                }
            }
        });

        // copy previous array of selected files
        File[] prevSelected = null;
        if (selected != null) {
            prevSelected = new File[selected.length];
            System.arraycopy( selected, 0, prevSelected, 0, selected.length );
        }

        int choice = chooser.showOpenDialog(this);

        // if the user did not cancel the selection
        if (choice == JFileChooser.APPROVE_OPTION) {
            System.out.println("FINAL selection: " + Arrays.toString(selected)); //debug
        } else {
            // restore the previous selection
            selected = prevSelected;
            System.out.println("PREVIOUS selection: " + Arrays.toString(selected)); //debug
        }
    }

}

答案 2 :(得分:0)

上面的代码经过修改,以按选择顺序显示在文本字段中

/*
 * FileName  :SelectedOrderedFileChooser.java
 */

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JTextField;
import javax.swing.plaf.metal.MetalFileChooserUI;

/**
 * File Chooser with selection order<br>
 * Only work for Ctrl + click selection
 */
public class SelectedOrderedFileChooser extends JFileChooser{

    /** Selection order file name list */
    private List<String> selectedFileNames = new ArrayList<String>();

    boolean isSelectionOrder = false;

    /**
     * Constructor
     */
    public SelectedOrderedFileChooser() {
        super();
        setSelectionOrder(false);
    }

    /**
     * Constructor
     * @param aIsSelectionOrder Selection ordered or not<br>
     * true : Selection order, false : File Name order(JFileChooser Default)
     */
    public SelectedOrderedFileChooser(boolean aIsSelectionOrder) {
        super();
        setSelectionOrder(aIsSelectionOrder);
    }
    /**
     * Get selected file names in selection order
     * @param fs Selected files
     * @return File names in selection order
     */
    private List<String> getFileNamesInSelectionOrder(File[] fs) {
        List<String> tmpSelectedFileNames = new ArrayList<String>();
        List<String> tmpResultFileNames = new ArrayList<String>();
        for (File f : fs) {
            // Get all current selected file names
            tmpSelectedFileNames.add(f.getAbsolutePath());
        }
        for (String fn : selectedFileNames) {
            if (tmpSelectedFileNames.contains(fn)) {
                // If ordered selected file name is in current selected file names, add to temporary file name list
                tmpResultFileNames.add(fn);
            }
        }

        // If there are current selected file names that is not in temporary file name list, add them
        for (String fn : tmpSelectedFileNames) {
            if (tmpResultFileNames.contains(fn) == false) {

                tmpResultFileNames.add(fn);
            }
        }
        return tmpResultFileNames;
    }

    /**
     * Get selected file names
     * @return Selected file names
     */
    public List<String> getSelectedFileNames() {
        return selectedFileNames;
    }

    /**
     * Is selection order or not?
     * @return true : Selection order, false : File Name order(JFileChooser Default)
     */
    public boolean isSelectionOrder() {
        return isSelectionOrder;
    }

    /**
     * Set whether file selection order or not.
     * @param aIsSelectionOrder true : Selection order, false : File Name order(JFileChooser Default)
     */
    public void setSelectionOrder(boolean aIsSelectionOrder) {
        this.isSelectionOrder = aIsSelectionOrder;
        this.addPropertyChangeListener(new PropertyChangeListener(){

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ( evt.getPropertyName().equals("SelectedFilesChangedProperty") ){
                    File[] fs = (File[])evt.getNewValue();
                    if (null != fs && fs.length > 0) {
                        if (isSelectionOrder) {
                             // If selection order、get file name in selection order and set to selected order file name list
                            List<String> tmpResultFileNames = getFileNamesInSelectionOrder(fs);
                            selectedFileNames = tmpResultFileNames;
                            showTextField();
                        } else {
                            // If not selection order、FileChooser default order
                            selectedFileNames.clear();
                            for (File f : fs) {
                                selectedFileNames.add(f.getAbsolutePath());
                            }
                        }
                    }
                }
            }
        });
    }

    /**
     * Get selection ordered files in array
     * @return selection ordered files in array
     */
    public File[] getSelectedOrderedFiles() {
        List<File> ret = new ArrayList<File>();
        for (String fName : selectedFileNames) {
            File f = new File(fName);
            ret.add(f);
        }
        return ret.toArray(new File[ret.size()]);
    }

    /**
     * Show file names in selection order in text field of JFileChooser
     */
    public void showTextField(){
        try {
            String res = "";
            for (File f : getSelectedOrderedFiles()) {
                res += "\"" + f.getName() + "\" ";
            }
            MetalFileChooserUI ui = (MetalFileChooserUI)this.getUI();
            Field field;
            field = MetalFileChooserUI.class.getDeclaredField("fileNameTextField");
            field.setAccessible(true);
            JTextField tf = (JTextField) field.get(ui);
            tf.setText(res.trim());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}