Does Swing support Windows 7-style file choosers?
Asked Answered
B

10

48

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

Brinton answered 18/4, 2011 at 13:46 Comment(0)
B
21

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 ();
    }
} 
Beamer answered 28/5, 2011 at 5:22 Comment(3)
This works, and although it's not technically Swing, it does appear to work just fine side-by-side with Swing.Brinton
How many MB overhead will using the SWT's filechooser add to a SWING application? — How much slower will the App start with SWT added to it? — I am tempted to vote all the “my GUI is better then yours” show-off answers down.Swirly
@Martin: I don't understand your animosity. I was trying to answer the question, not be a show-off. The question asked if this could be done in Swing. My answer is it can't be done in Swing and to provide a viable alternative. I agree that profiling this solution is important, but I believe it is outside of the scope of this question. Also, it would probably be best to profile this solution as part of the application. I doubt that this solution contributes significant overhead to the application, but the application would be best profiled as a whole.Beamer
T
10

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.

Tenderhearted answered 31/5, 2011 at 6:20 Comment(4)
Barring a spectacular last-minute answer, this is going to get the bounty for its comprehensiveness.Brinton
The Swing dialog is a completely Java-based dialog (with an XP-clone LAF), and not a native dialog. It is not simply a side effect of how Java uses native calls (though those can also generate an XP-like file dialog).Dehlia
@MichaelBrewer-Davis You are right. I ignored the fact that Swing is pure Java. Using Spy++ confirms this: the class of the dialog window is SunAwtDialog, and it has no child windows as opposed to standard system dialog. Moreover it looks very similar to XP open file dialog but it's not the same: there behavioral and appearance differences.Tenderhearted
A JNI solution seems to be implemented in code.google.com/p/xfiledialog, this may be also a viable option.Decolorant
P
8

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);
});
Presumptuous answered 18/4, 2011 at 13:46 Comment(3)
Tip: JavaFX is specific to Oracle Java only, so you may need to select this explicitly, e.g. in your Eclipse project. By contrast, "Java-1.8 execution environment" would correctly exclude JavaFX from being visible in the classpath.Presumptuous
showOpenDialog(null) does not specify a parent/owner window and so the pop-up is not modal. It's expecting a javafx.stage.Window but I'm working with Swing's java.awt.Window. How could I achieve a modal FileChooser?Voluntaryism
You may have misread "modern dialog" as modal dialog? Anyway, I don't think you can create a parent (let alone modal) relationship between JavaFX and Swing windows (due to their different threading models, event loops, incompatible code bases...) See this answer which basically hacks it by blocking one window and forcing focus back to the other. It's flawed - multiple Top-level Frames appear in the Task Bar, and the hackery doesn't work on some Linux window managers. Still it's the best I've seen to date...Presumptuous
K
7

A bit of a hack, and slightly less empowered than the Swing version, but have you considered using a java.awt.FileDialog? It should not just look like the Windows file chooser, but actually be one.

Keck answered 18/4, 2011 at 14:1 Comment(4)
Sadly, this does not work; it also brings up the XP-style dialog. The test code I used came directly from java2s.com/Code/JavaAPI/java.awt/…Brinton
What about this one?Humbertohumble
@trashgod: In the coming hours I will be starting a new thread titled 'File Manager' devoted to an expanded version of that code. When I do I'll add a comment to the thread you linked, and hope to see you over on the newest thread.Keck
+1 because this may be an adequate solution for some scenarios. At least you can delete files, get a context menu, etc... Just beware of MAJOR limitations: file filtering doesn't work on Windows, and no support for multiple file selection. <rant>Java 7 enhanced this ancient class a tiny bit. I can understand the focus is moving away from Swing, but I still can't believe they can't do just a little more, for this fundamentally important dialog! </rant>Presumptuous
S
7

I don't believe Swing would cover that though it may, if it doesn't you may need to look at something like SWT, which would make use of the actual native component, or do a custom UI element, like something out of the "Filthy Rich Clients" book.

Solana answered 18/4, 2011 at 15:28 Comment(0)
K
2

good question +1 , looks like as they "forgot" to implements something for Win7 (defaultLookAndFeel) into Java6, but for WinXP works correclty, and I hope too, that there must exists some Method/Properties for that

anyway you can try that with this code,

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() {
    }
}
Kolnos answered 25/5, 2011 at 11:21 Comment(1)
Just tried this, it still gives a chooser similar to my first screenshot. I appreciate the effort, though.Brinton
M
1

Couldn't make this work for directories though!! The DirectoryDialog throws us back to the tree style directory chooser which is the same as the one listed in the question. The problem is that it does not allow me to choose/select/open hidden folders. Nor does it allow for navigation to folders like AppData, ProgramData etc..

The Windows 7 style filedialog (swt) does allow navigation to these folders, but then again, does not allow for folder selection :(

Update To view hidden folders use JFileChooser and have setFileHidingEnabled(false). The only mandate with this is that users need to have 'show hidden files, folders and drives' selected in the

Folder Options -> View

of Windows Explorer

You won't get the flexibility of an address bar, but if you were looking around for a non-tree like file chooser in Java, which also lets you browse/view Hidden files/folder - then this should suffice

Maltha answered 8/6, 2013 at 6:58 Comment(0)
O
1

John McCarthy's answer seems to be the best. Here some suggestions.

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

Add image on top left corner. It's important that you use "getResourceAsStream", you'll notice after export as 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));
}

User's home directory:

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

Get absolut pathname instead of filter-dependent pathname, which is wrong on other drive.

String absolutePath = dialog.open();
Orin answered 28/7, 2015 at 12:15 Comment(0)
F
0

Since Swing emulates various L&F's, I guess your best bet would be to upgrade your JRE to the very latest and hope that the JFileChooser UI has been updated.

Fir answered 18/4, 2011 at 14:58 Comment(0)
A
0

JFileChooser has always been a bit odd looking with Swing, also a bit slow.

Try using SWT's filechooser or you could wrap the C calls in JNA.

Alten answered 24/5, 2011 at 21:46 Comment(1)
How many MB overhead will using the SWT's filechooser add to a SWING application? — How much slower will the App start with SWT added to it? — I am tempted to vote all the “my GUI is better then yours” show-off answers down.Swirly

© 2022 - 2024 — McMap. All rights reserved.