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

Java JFileChooser按单击顺序打开多个文件,java,swing,jfilechooser,look-and-feel,Java,Swing,Jfilechooser,Look And Feel,我有一个应用程序,它接收多个文件,并根据它们的顺序应用一些操作(例如,一个接一个地合并它们) 用户可以通过Ctrl+单击或Shift+单击按任意顺序选择文件 选择器返回的列表文件的顺序与用户单击的顺序不同。我希望返回的顺序与用户单击的顺序相同 免责声明:我是“用户” 我正在使用JFileChooser类,该类在64位Windows 7和JDK 7上具有Java外观 这里有一个最小的例子 package choosertest; import java.io.File; import javax

我有一个应用程序,它接收多个文件,并根据它们的顺序应用一些操作(例如,一个接一个地合并它们)

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

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

免责声明:我是“用户”

我正在使用
JFileChooser
类,该类在64位Windows 7和JDK 7上具有Java外观

这里有一个最小的例子

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());
            }
        }
    }

}

<> P>而不是按JFLeLe选择器中的选择顺序排序文件,您可以考虑在使用JTab/JLIST之类的选择之后重新排序文件。尽管如此,通过向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()返回的文件数组,以查看选择(或取消选择)了哪个新文件以保持顺序。

我已经知道,Ctrl+单击工作,Shift+单击“向下”选择文件工作

但是,使用Shift+单击“向上”选择文件仍然会以错误的顺序添加文件,这可能会造成混淆

此外,此解决方案不会更新“文件名”文本字段以反映选择的实际顺序。不过,可以使用反射来“修复”这个问题

如果您需要一个快速解决方案,通过按住Ctrl键并单击文件来按正确的顺序选择文件,那么这很好(选择和取消选择)

包选择测试;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.io.File;
导入java.util.array;
导入java.util.LinkedList;
导入java.util.List;
导入javax.swing.JFileChooser;
导入javax.swing.JFrame;
公共类选择器测试扩展了JFrame{
选择文件[];
JFileChooser选择器;
公共选择器测试(){
chooser=newjfilechooser();
选择器。setMultiSelectionEnabled(真);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(真);
testOpen();
}
公共静态void main(字符串[]args){
新建选择器测试();
}
私有void testOpen(){
addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
if(evt.getPropertyName().equals(“SelectedFilesChangedProperty”)){
如果(所选==null){
selected=(文件[])evt.getNewValue();
}否则{
文件[]newSelection=(文件[])evt.getNewValue();
if(newSelection==null){
选中=空;
}
//来回检查以保持文件的顺序
//当用户添加它们时
否则{
List orderedSel=new LinkedList();
//添加仍处于选中状态的文件
对于(文件f:已选定){
for(文件f2:新闻选举){
如果(f等于(f2)){
订单选择添加(f);
打破
}
}
}
数组。排序(选定);
//添加新选择的文件
用于(文件f:newSelection){
if(Arrays.binarySearch(selected,f)<0){
订单选择添加(f);
}
}
所选=orderedSel.toArray(
新文件[orderedSel.size()];
}
}
System.out.println(Arrays.toString(选中));//调试
}
}
});
//复制选定文件的上一个数组
文件[]prevSelected=null;
如果(已选择!=null){
prevSelected=新文件[selected.length];
System.arraycopy(选中,0,prevSelected,0,selected.length);
}
int choice=chooser.showOpenDialog(此);
//如果用户没有取消选择
if(choice==JFileChooser.APPROVE\u选项){
System.out.println(“最终选择:“+Arrays.toString(已选择));//调试
}否则{
//恢复以前的选择
已选择=已选择;
System.out.println(“上一个选择:“+Arrays.toString(已选择));//调试
}
}
}

修改了上述代码,以便在文本字段中按选择顺序显示

/*
 * 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();
        }
    }
}
/*
*文件名:SelectedOrderedFileChooser.java
*/
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.io.File;
导入java.lang.reflect.Field;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JFileChooser;
导入javax.swing.JTextField;
导入javax.swing.plaf.metal.MetalFileChooserUI;
/**
*具有选择顺序的文件选择器
*仅适用于Ctrl+单击选择 */ 公共类SelectedOrderedFileChooser扩展了JFileChooser{ /**选择顺序文件名列表*/ private List selectedFileNames=new ArrayList(); 布尔值isSelectionOrder=false; /** *建造师 */ public SelectedOrderedFileChooser(){ 超级(); 设置选择顺序(假); } /**
/*
 * 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();
        }
    }
}