Поддерживает ли Swing средство выбора файлов в стиле Windows 7? - PullRequest
47 голосов
/ 18 апреля 2011

Я только что добавил стандартное диалоговое окно « Открыть файл » для небольшого настольного приложения, которое я пишу, на основе записи JFileChooser в Swing Tutorial . Он генерирует окно, которое выглядит так:

screenshot of unwanted/XP-style window

но я бы предпочел иметь окно, которое выглядит так:

screenshot of desired/7-style window

Другими словами, я хочу, чтобы средство выбора файлов имело стиль Windows Vista / Windows 7, а не Windows XP. Возможно ли это в Swing? Если так, как это сделано? (Для целей этого вопроса предположим, что код будет работать исключительно на компьютерах с Windows 7.)

Ответы [ 10 ]

21 голосов
/ 28 мая 2011

Не похоже, что это поддерживается в Swing в Java 6.

В настоящее время самый простой способ открыть это диалоговое окно - через SWT, а не Swing. FileDialog SWT ( javadoc ) вызывает это диалоговое окно. Ниже приведена модификация фрагмента SWT FileDialog для использования диалога открытия вместо сохранения. Я знаю, что это не совсем то, что вы ищете, но вы можете выделить это для служебного класса и добавить swt.jar в ваш путь к классам для этой функциональности.

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

public class SWTFileOpenSnippet {
    public static void main (String [] args) {
        Display display = new Display ();
        Shell shell = new Shell (display);
        // Don't show the shell.
        //shell.open ();  
        FileDialog dialog = new FileDialog (shell, SWT.OPEN | SWT.MULTI);
        String [] filterNames = new String [] {"All Files (*)"};
        String [] filterExtensions = new String [] {"*"};
        String filterPath = "c:\\";
        dialog.setFilterNames (filterNames);
        dialog.setFilterExtensions (filterExtensions);
        dialog.setFilterPath (filterPath);
        dialog.open();
        System.out.println ("Selected files: ");
        String[] selectedFileNames = dialog.getFileNames();
        for(String fileName : selectedFileNames) {
            System.out.println("  " + fileName);
        }
        shell.close();
        while (!shell.isDisposed ()) {
            if (!display.readAndDispatch ()) display.sleep ();
        }
        display.dispose ();
    }
} 
11 голосов
/ 31 мая 2011

Даже родные приложения Windows могут отображать этот тип диалога в Windows 7. Обычно это контролируется флагами в структуре OPENFILENAME и ее размером, передаваемым при вызове функции WinAPI GetOpenFileName. Swing (Java) использует хуки для получения событий из диалога Open File; эти события передаются по-разному между Windows XP и версией Windows 7.

Таким образом, ответ таков: вы не можете контролировать внешний вид FileChooser из Swing. Однако, когда Java получит поддержку этого нового стиля, вы получите новый стиль автоматически.

Другой вариант - использовать SWT, как предложено в в этом ответе . В качестве альтернативы вы можете использовать JNA для вызова Windows API или написать собственный метод для этого.

7 голосов
/ 22 августа 2014

Java 8 может, наконец, принести решение этой проблемы, но, к сожалению (для приложений Swing), оно приходит только как класс JavaFX FileChooser :

Я тестировал этот код с здесь и это действительно всплывающее современное диалоговое окно (здесь Windows 7):

FileChooser fileChooser = new FileChooser();

//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

//Show open file dialog
File file = fileChooser.showOpenDialog(null);

Чтобы интегрировать это в приложение Swing, вам нужно будет запустить его в потоке javafx через Platform.runLater(как видно здесь ).

Обратите внимание, что для этого потребуется инициализация потока javafx (в данном примере это делается при инициализации сцены в new JFXPanel()).

Подводя итог, можно сказать, что готовое решение в Swing-приложении будет выглядеть так:

new JFXPanel(); // used for initializing javafx thread (ideally called once)
Platform.runLater(() -> {
    FileChooser fileChooser = new FileChooser();

    //Set extension filter
    FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
    FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
    fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

    //Show open file dialog
    File file = fileChooser.showOpenDialog(null);
});
7 голосов
/ 18 апреля 2011

Я не верю, что Swing охватит это, хотя может, если нет, вам может понадобиться посмотреть на что-то вроде SWT, которое будет использовать реальный нативный компонент, или создать пользовательский элемент пользовательского интерфейса, например из книги "Грязные богатые клиенты".

7 голосов
/ 18 апреля 2011

Немного взломано и немного менее мощно, чем версия Swing, но вы рассматривали возможность использования java.awt.FileDialog?Он должен не просто выглядеть как средство выбора файлов Windows, но на самом деле быть единым.

2 голосов
/ 25 мая 2011

хороший вопрос +1, похоже, что они «забыли» реализовать что-то для Win7 (defaultLookAndFeel) в Java6, но для WinXP работает корректно, и я тоже надеюсь, что для этого

должен существовать некоторый метод / свойства

в любом случае вы можете попробовать это с этим кодом,

import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;

class ChooserFilterTest {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                String[] properties = {"os.name", "java.version", "java.vm.version", "java.vendor"};
                for (String property : properties) {
                    System.out.println(property + ": " + System.getProperty(property));
                }
                JFileChooser jfc = new JFileChooser();
                jfc.showOpenDialog(null);
                jfc.addChoosableFileFilter(new FileFilter() {

                    @Override
                    public boolean accept(File f) {
                        return f.isDirectory() || f.getName().toLowerCase().endsWith(".obj");
                    }

                    @Override
                    public String getDescription() {
                        return "Wavefront OBJ (*.obj)";
                    }

                    @Override
                    public String toString() {
                        return getDescription();
                    }
                });
                int result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
                System.out.println("Displayed description (Metal): " + (result == JOptionPane.YES_OPTION));
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    SwingUtilities.updateComponentTreeUI(jfc);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                jfc.showOpenDialog(null);
                result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
                System.out.println("Displayed description (System): " + (result == JOptionPane.YES_OPTION));
            }
        };
        SwingUtilities.invokeLater(r);
    }

    private ChooserFilterTest() {
    }
}
1 голос
/ 28 июля 2015

Ответ Джона Маккарти кажется лучшим.Вот несколько предложений.

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;

Добавьте изображение в верхнем левом углу.Важно, чтобы вы использовали "getResourceAsStream", после экспорта вы заметите как Runnable jar:

Display display = new Display();
Shell shell = new Shell(display);
InputStream inputImage = getClass().getResourceAsStream("/app/launcher.png");
if (inputImage != null) {
    shell.setImage(new Image(display, inputImage));
}

Домашний каталог пользователя:

String filterPath = System.getProperty("user.home");

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

String absolutePath = dialog.open();
1 голос
/ 08 июня 2013

Не могу сделать эту работу для каталогов, хотя! DirectoryDialog возвращает нас к средству выбора каталогов в стиле дерева, которое совпадает с указанным в вопросе. Проблема в том, что он не позволяет мне выбирать / выбирать / открывать скрытые папки. Также он не позволяет перемещаться по папкам, таким как AppData, ProgramData и т. Д.

Диалог файлов в стиле Windows 7 (SWT) разрешает переход к этим папкам, но, опять же, не позволяет выбирать папки: (

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

Параметры папки -> Просмотр

Windows Explorer

Вы не получите гибкости адресной строки, но если вы искали в Java средство выбора файлов, не похожее на дерево, которое также позволяет вам просматривать / просматривать скрытые файлы / папки - тогда этого должно быть достаточно

0 голосов
/ 25 мая 2011

JFileChooser всегда был немного странным с Swing, также немного медленным.

Попробуйте использовать средство выбора файлов SWT, или вы можете обернуть вызовы C в JNA.

0 голосов
/ 18 апреля 2011

Поскольку Swing эмулирует различные L & F, я думаю, что вам лучше всего обновить вашу JRE до самой последней версии и надеяться, что пользовательский интерфейс JFileChooser был обновлен.

...