我有一个应用程序,它接受多个文件并应用一些取决于它们的顺序的操作(例如,一个接一个地合并它们)。
用户可以通过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());
}
}
}
}
答案 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 +单击选择文件"向上"仍然以错误的顺序添加文件,这可能令人困惑。
此外,此解决方案不会更新"文件名"文本字段以反映选择的实际顺序。有可能"修复"但是,这可以使用反射。
如果您需要一个快速解决方案,通过按住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();
}
}
}