JFileChooser выбирает каталог, но показывает файлы

Я чувствую, что должен быть простой способ сделать это, но я не могу понять это. У меня есть JFileChooser, который позволяет пользователю выбирать каталоги. Я хочу показать все файлы в каталогах, чтобы дать пользователю некоторый контекст, но в качестве выбора следует принимать только каталоги (возможно, кнопка «Открыть» будет отключена при выборе файла). Есть ли простой способ сделать это?


person Jeff Storey    schedule 21.05.2010    source источник


Ответы (9)


Переопределите метод AppSelection(). Что-то типа:

JFileChooser chooser = new JFileChooser( new File(".") )
{
    public void approveSelection()
    {
        if (getSelectedFile().isFile())
        {
            // beep
            return;
        }
        else
            super.approveSelection();
    }
};
person camickr    schedule 21.05.2010

Мое решение представляет собой слияние ответов camickr и trashgod:

    final JFileChooser chooser = new JFileChooser() {
            public void approveSelection() {
                if (getSelectedFile().isFile()) {
                    return;
                } else
                    super.approveSelection();
            }
    };
    chooser.setFileSelectionMode( JFileChooser.FILES_AND_DIRECTORIES );
person ablaeul    schedule 21.05.2010
comment
+1 Похоже, я в хорошей компании! Я обновил свой ответ, чтобы отразить этот комбинированный подход. - person trashgod; 22.05.2010
comment
Очень хороший! JFileChooser.FILES_AND_DIRECTORIES важно! Без него (как в ответе camickr) решение бесполезно, как я тестировал. - person java.is.for.desktop; 19.01.2011

См. setFileSelectionMode() в Как использовать средства выбора файлов :

setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)

Приложение: Эффект можно увидеть, раскомментировав строку 73 этого FileChooserDemo, но похоже, что это зависит от платформы.

Приложение: Если вы используете FILES_AND_DIRECTORIES, рассмотрите возможность соответствующего изменения текста кнопки:

chooser.setApproveButtonText("Choose directory");

Поскольку эффект зависит от L&F, рассмотрите возможность использования DIRECTORIES_ONLY на платформах, которые уже соответствуют вашим требованиям к пользовательскому интерфейсу:

if (System.getProperty("os.name").startsWith("Mac OS X")) {
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
    chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
}
person trashgod    schedule 21.05.2010
comment
Но это скроет файлы, чего он не хочет. - person Michael Myers; 21.05.2010
comment
@mmyers: в ​​приведенном выше примере файлы отображаются серым цветом. YMMV - person trashgod; 21.05.2010
comment
Из того, что говорится в учебнике, кажется, что это зависит от laf. - person Michael Myers; 21.05.2010
comment
@mmyers: Эмпирически это зависит от платформы: файлы отображаются серым цветом во всех поддерживаемых L&F в Mac OS X. - person trashgod; 21.05.2010
comment
Красивое объяснение, спасибо! Дополнительный совет о пользовательском интерфейсе платформы — это здорово. - person Xyene; 15.05.2013

Решение переопределения approveSelection может раздражать некоторых пользователей.

Иногда пользователь просто без причины щелкает файл в каталоге (даже если он хочет выбрать каталог, а не файл). Если это произойдет, пользователь (своего рода) застрянет в JFileChooser, так как approveSelection потерпит неудачу, даже если он отменит выбор файла. Чтобы избежать этого раздражения, я делаю следующее:

JFileChooser fileChooser = new JFileChooser();

fileChooser.setFileSelectionMode(
        JFileChooser.FILES_AND_DIRECTORIES);

int option = fileChooser.showDialog(null,
        "Select Directory");

if (option == JFileChooser.APPROVE_OPTION) {
    File f = fileChooser.getSelectedFile();
    // if the user accidently click a file, then select the parent directory.
    if (!f.isDirectory()) {
        f = f.getParentFile();
    }
    System.out.println("Selected directory for import " + f);
}

Выбор каталога, даже когда пользователь выбрал файл, на мой взгляд, приводит к лучшему удобству использования.

person Ankit    schedule 02.05.2013

AFAIK JFileChooser отделяет фильтрацию файлов (что можно просмотреть, очень настраивается) от фильтрации выбора (что можно выбрать).

Конфигурация фильтрации выбора гораздо более ограничена, но, насколько мне известно, вы можете разрешить выбор только каталогов или только файлов с помощью setFileSelectionMode()

person Uri    schedule 21.05.2010

Сохраните fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) и используйте:

File[] selectedFiles = fileChooser.getSelectedFile().listFiles();
person alexandre1985    schedule 16.02.2015

JFileChooser поддерживает три режима выбора: только файлы, только каталоги и файлы и каталоги. В вашем случае вам нужно:

JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

источник: http://www.java2s.com/Tutorial/Java/0240__Swing/TheJFileChoosersupportsthreeselectionmodesfilesonlydirectoriesonlyandfilesanddirectories.htm

person Mehdi    schedule 18.02.2020

Выбрать несколько папок, но показать все включенные файлы

    import javax.swing.*;
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    
    public class MultipleFilesAndDirectoryChooserButDisplayFiles {
        public static void main(String[] args) {
            ArrayList<File> tempFiles = new ArrayList<>();
            ArrayList<File> finalFiles = new ArrayList<>();
            ArrayList<String> relativeFiles = new ArrayList<>();
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setDialogTitle("Choose File To Transfer");
            fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
            fileChooser.setMultiSelectionEnabled(true);
            int returnVal = fileChooser.showOpenDialog(null);
            fileChooser.approveSelection();
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                fileChooser.approveSelection();
                var fileAddress = fileChooser.getSelectedFiles();
                for (var arrElement : fileAddress) {
                    tempFiles.add(arrElement);
                    File baseFile;
                    baseFile = arrElement.getParentFile();
                    Iterator<File> iterator = tempFiles.iterator();
                    while (iterator.hasNext()) {
                        File file = iterator.next();
                        if (file.isDirectory()) {
                            var enclosedFiles = file.listFiles();
                            if (enclosedFiles != null) {
                                if (enclosedFiles.length != 0) {
                                    var index = tempFiles.indexOf(file);
                                    tempFiles.remove(file);
                                    tempFiles.addAll(index, Arrays.asList(enclosedFiles));
                                    iterator = tempFiles.iterator();
                                } else {
                                    tempFiles.remove(file);
                                    finalFiles.add(file);
                                    relativeFiles.add(baseFile.toURI().relativize(file.toURI()).getPath());
                                    iterator = tempFiles.iterator();
                                }
                            }
                        } else if (file.isFile()) {
                            tempFiles.remove(file);
                            finalFiles.add(file);
                            relativeFiles.add(baseFile.toURI().relativize(file.toURI()).getPath());
                            iterator = tempFiles.iterator();
                        }
                    }
    
    
                }
                for (var relativeFile : relativeFiles) {
                    System.out.println(relativeFile);
    
                }
                for (var file : finalFiles) {
                    System.out.println(file);
                }
    
            }
        }
    }

Вывод:

  • Папка1/пустая папка/

  • Папка1/Подпапка1/1.1.txt

  • Папка1/Подпапка1/1.2.txt

  • Папка1/Подпапка1/1.3.txt

  • Папка1/Подпапка1/Подпапка 1.1/1.1.1.txt

  • Папка1/Подпапка1/Подпапка 1.1/1.2.1.txt

  • Папка1/Подпапка1/Подпапка 1.1/1.3.1.txt

  • Папка1/Подпапка2/2.1/2.1.1.txt

  • Папка1/Подпапка2/2.1/2.1.2.txt

  • Папка1/Подпапка2/2.1/2.1.3.txt

  • Папка1/Подпапка3/3.1.txt

  • Папка1/Подпапка3/3.2.txt

  • Папка1/Подпапка3/3.3.txt

  • Папка2/Подпапка/2.1.txt

  • Папка2/Подпапка/ПустойПапка/

  • файл1.txt

  • файл2.txt

  • E:\Folder1\EmptyFolder

  • E:\Folder1\SubFolder1\1.1.txt

  • E:\Folder1\SubFolder1\1.2.txt

  • E:\Folder1\SubFolder1\1.3.txt

  • E:\Folder1\SubFolder1\SubFolder 1.1\1.1.1.txt

  • E:\Folder1\SubFolder1\SubFolder 1.1\1.2.1.txt

  • E:\Folder1\SubFolder1\SubFolder 1.1\1.3.1.txt

  • E:\Folder1\SubFolder2\2.1\2.1.1.txt

  • E:\Folder1\SubFolder2\2.1\2.1.2.txt

  • E:\Folder1\SubFolder2\2.1\2.1.3.txt

  • E:\Folder1\SubFolder3\3.1.txt

  • E:\Folder1\SubFolder3\3.2.txt

  • E:\Folder1\SubFolder3\3.3.txt

  • E:\Folder2\Подпапка\2.1.txt

  • E:\Folder2\Подпапка\EmptyFolder

  • E:\file1.txt

  • E:\file2.txt

person k4b1n    schedule 24.07.2020

Я думаю, что лучшее решение — просто позволить пользователю выбрать файл или каталог. И если пользователь выбирает файл, просто используйте каталог, в котором находится этот файл.

person Martin Tilsted    schedule 21.05.2010