Does Swing support Windows 7-style file choosers?

I just added a standard "Open file" dialog to a small desktop app I'm writing, based on the JFileChooser entry of the Swing Tutorial. It's generating a window that looks like this:

screenshot of unwanted/XP-style window

but I would prefer to have a window that looks like this:

screenshot of desired/7-style window

In other words, I want my file chooser to have Windows Vista/Windows 7's style, not Windows XP's. Is this possible in Swing? If so, how is it done? (For the purposes of this question, assume that the code will be running exclusively on Windows 7 computers.)


Solution 1:

It does not appear this is supported in Swing in Java 6.

Currently, the simplest way I can find to open this dialog is through SWT, not Swing. SWT's FileDialog (javadoc) brings up this dialog. The following is a modification of SWT's FileDialog snippet to use an open instead of save dialog. I know this isn't exactly what you're looking for, but you could isolate this to a utility class and add swt.jar to your classpath for this functionality.

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

Solution 2:

Even native Windows applications can get this type of dialog displayed on Windows 7. This is usually controlled by flags in OPENFILENAME structure and its size passed in a call to WinAPI function GetOpenFileName. Swing (Java) uses hooks to get events from the Open File dialog; these events are passed differently between Windows XP and Windows 7 version.

So the answer is you can't control the look of FileChooser from Swing. However, when Java gets support for this new look, you'll get the new style automatically.

Another option is to use SWT, as suggested in this answer. Alternatively you can use JNA to call Windows API or write a native method to do this.

Solution 3:

Java 8 may finally bring a solution to this, but unfortunately (for Swing apps) it comes only as the JavaFX class FileChooser:

I've tested this code from here and it indeed pops a modern dialog (Windows 7 here):

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

To integrate this into a Swing app, you'll have to run it in the javafx thread via Platform.runLater (as seen here).

Please note that this will need you to initialize the javafx thread (in the example, this is done at the scene initialization, in new JFXPanel()).

To sum up, a ready to run solution in a swing app would look like this :

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