The Swing File
Chooser
Changes
Made in V1.0.2 Are Permanent Now
By Jeff Dinkins
In
Swing 1.0.2, the Swing team modified the JFileChooser class to reflect
both a simplification of its APIs and additional features requested
by developers. With the release of JDK 1.2, these changes become
a permanent part of Swing.
This article describes and illustrates the new features of the
Swing file chooser, and presents some sample code -- including a
complete application -- to show how you can use the new file chooser
in your Swing applets and applications.
Major topics covered in this article are:
Downloading
the examples
A
number of code samples are presented in this article. If you're
not keen about retyping them, you can download a full set of file-chooser
examples by following these links:
- Click here
to see the source code for a comprehensive file-chooser application
named FileChooserExample.java.
- Click here
to download a compressed file named example.zip that contains
a file-chooser example.
First, the basics. One of the goals for JFileChooser was to make
it very easy to create and use in it's simplest forms: as an "Open"
file chooser or as a "Save As" file chooser. For example,
you can create an "Open" file chooser like this one by
writing just a few lines of code:
Example: Creating an 'Open' file
chooser
To pop up an "Open"
file chooser like the one shown above, all you have to do is write
a code sequence something like this:
FileChooser
filechooser = new JFileChooser();
if(filechooser.showOpenDialog(frame) ==
JFileChooser.APPROVE_OPTION) {
File f = filechooser.getSelectedFile();
System.out.println
("This file was chosen for opening: " + f);
} else {
System.out.println
("No file was chosen or an error occured");
};
Example: Displaying a 'Save As'
chooser
To pop up a "Save
As" file chooser like the one shown below, you can execute
a similar code sequence:
Here's the code that creates and displays the "Save As"
file chooser shown above:
JFileChooser
filechooser = new JFileChooser();
if(filechooser.showSaveDialog(frame)
==
JFileChooser.APPROVE_OPTION)
{
File f = filechooser.getSelectedFile();
System.out.println
("This file was chosen for saving: " + f);
} else {
System.out.println
("No file
was chosen or an error occurred");
};
File
choosers don't save files
It's
important to note that file-chooser dialogs don't actually open
or save files. Rather, a file chooser returns a File object that
the developer can then do with as she pleases. But it would confuse
the user terribly if your application decided to pop up, for example,
a Save As file chooser, and then did not actually save to the
file that was subsequently chosen. It's up to the developer to
use good user interface design and use JFileChooser in a logical
manner.
In the current version of Swing, the file-chooser classes with
major changes or additions are:
- The FileView class: The FileType and TypedFile used
in Swing 1.0.1 have been replaced with a new abstract class named
FileView. For more details, see the next section, "The
FileView class."
- The FileFilter class: FileFilter is an abstract class
that you can implement to filter out files that you don't want
to appear in your file chooser''s list of files.
- The JFileChooser class: JFileChooser now has several
customizable features. We'll examine each one of these more closely
in the subsection titled "The JFileChooser
class."
- The FileSystemView class: We don't anticipate that many
(if any) developers will need to use -- or know about -- this
class. So you get to the subsection titled "The
FileSystemView class," you can skip it and not worry
about missing anything. Those who are just curious can go ahead
and read it anyway.
Under the subheadings that follow, each of these classes is described
in more detail.
The
FileView class
The FileView class
allows the developer to provide custom view information, such as
an icon for a file or a type name, to the FileChooser.
Later in this article, in the "Creating
a custom file view" section, you'll find source code that
shows how to create special views using the FileView class.
The
FileChooser class
The newest version
of the JFileChooser class has several customizable features (we'll
examine each one of these more closely in the later in this article,
in the section titled "The
file chooser in depth"):
- The ability to pop up a file chooser dialog that has a different
notion than "Open" or "Save." For example,
this is a "Run It" file chooser:
- Settable user-chooseable file filters, as shown below:
- An area in the JFileChooser in which the developer can add his
or her own accessory component. This area is most commonly used
to plug in file previewer object, but can also be used to throw
in additional file-selection options, or (as illustrated below)
anything else the developer can dream up.
- The ability to bring up a chooser as either a file chooser,
a directory chooser, or both.
The
FileSystemView class
The FileSystemView
class -- which most developers will probably never need to know
about -- is a "gateway" that the FileChooser uses to get
to the file system. This strategy has two main purposes, only one
of which is used in the provided implementation:
- FileSystemView provides operating system independent information
about the file system that the io.File
class does not yet provide (although JDK 1.2 and beyond may perform
this functionality later).
For example, FileSystemView.getRoots()
returns the roots of the OS-specific file system. (On Windows,
this would be any mounted A: through Z: drives.
On UNIX, it would just be "/".) Licensees of the JavaTM
programming language might very well provide other implementations
of FileSystemView that deal with their specific file systems.
- FileSystemView is responsible for all file-creation and file-listing
operations. For example, the FileChooser itself never calls "new
io.File()". Rather, JFileChooser goes through the
FileSystemView class when it wants to instantiate a new file object.
This convention may be of use to a developer who wants to subtype
io.File() to do some additional
(or altogether different) functionality than the io.File
class.
This section presents some source-code examples that show how to
use the new and improved features in the Swing file-chooser API.
Creating
a custom file chooser
We received many
requests for a popup file chooser that has a notion of what it should
do other than "Open" or "Save": For example,
developers have asked for mechanisms that can create such things
as "Run It" file choosers and "Delete" file
chooser.
It's very easy to create specialized file choosers in Swing. All
you have to do is execute a method such as this:
int
returnVal =
filechooser.showDialog(frame,"Run It");
Displaying file and directory choosers
You can bring up
the file chooser as either a file chooser, a directory
chooser, or as both. For example, to set the chooser to be a
directory chooser, you could execute a pair of statements like these:
JFileChooser
filechooser = new JFileChooser();
filechooser.setFileSelectionMode
(JFileChooser.DIRECTORIES_ONLY);
Creating file filters
With the FileFilter
class, you can create file filters and set user-selectable file
filters. FileFilter has just two methods:
public
boolean accept(File f);
public String getDescription();
JFileChooser
calls the accept() method
over every file to determine if the file should be added the file
list. The getDescription()
method returns a human-readable description of the file filter --
for example, "JPG Images (*.jpg)."
Here's a very simple example of a file filter that just accepts
image files:
class MyFilter
extends FileFilter {
final static String jpg = "jpg";
final static String gif = "gif";
final static String tiff = "tiff";
// Accept all directories and (gif
||
// jpg || tiff) files.
public boolean accept(File f) {
if(f.isDirectory())
{
return true;
}
String s = f.getName();
int i = s.lastIndexOf('.');
if(i > 0 && i <
s.length() - 1) {
String extension
=
s.substring(i+1).toLowerCase();
if (tiff.equals(extension)
|| gif.equals(extension)
|| jpg.equals(extension)) {
return true;
} else {
return false;
}
};
return false;
}
// The description of this filter
public String getDescription() {
return "Just Images (*.jpg,
*.gif, *.tiff)";
}
}
JFileChooser filechooser = new JFileChooser();
filechooser.addChoosableFileFilter(new MyFilter());
A
more complex file-filter example
A
much more complex example of a FileFilter implementation (based
on filename extensions) is now supplied with Swing. You can find
the code in the ExampleFileFilter.java file, inside the
examples/FileChooserDemo directory. We hope that the file
filter demonstrated in this example will handle most developer
file filtering needs, and we are currently considering incorporating
it into the core Swing release.
Your comments on this issue are most welcome; mail them to swing-feedback@java.sun.com.
Creating a
custom file view
The next code example
shows how to create a custom FileView that returns specific view
information. Specifically, the FileView that the program creates
returns file-view information about various image file types.
When you compile and execute the program, note that if any methods
return NULL, the program returns the default UI's FileView is returned
instead of the requested information. For example, if you return
NULL for the icon because you don't know what filetype the given
file is, the JFileChooser's UI file view returns a generic folder
icon or generic file icon, whichever is appropriate.
When you write code that uses the FileView class, you should understand
that JFileChooser knows about two FileView objects: the developer-set
file view, and a default "fallback" FileView that is determined
by the current look and feel. If the developer-set FileView is NULL,
or if an application's FileView method returns null, JFileChooser
uses this "fallback" FileView to obtain view information
(icons, strings) for the file.
Here's the source code for the FileView program:
class MyFileView extends
FileView {
ImageIcon jpgIcon = new ImageIcon("jpgIcon.gif");
ImageIcon gifIcon = new ImageIcon("gifIcon.gif");
ImageIcon tiffIcon = new ImageIcon("tiffIcon.gif");
public String getName(File f) {
return null; // let the FileView
figure this out
}
public String getDescription(File f) {
return null; // let the FileView
figure this out
}
public String getTypeDescription(File f) {
String extension = getExtension(f);
String type = null;
if(extension != null) {
if(extension.equals("jpg"))
{
type = "JPeg Image";
}
if(extension.equals("gif")){
type = "GIF Image";
}
if(extension.equals("tiff"))
{
type = "TIFF Image";
}
}
return type;
}
public Icon getIcon(File f) {
String extension = getExtension(f);
// System.out.println("extension
= " + extension);
Icon icon = null;
if(extension != null) {
if(extension.equals("jpg"))
{
icon = jpgIcon;
}
if(extension.equals("gif"))
{
icon = gifIcon;
}
if(extension.equals("tiff"))
{
icon = tiffIcon;
}
}
return icon;
}
public Boolean isTraversable(File f) {
return null; // let the FileView
// figure this out
}
// Get the extension of this file.
// Code is factored out
// because we use this in both getIcon and
// getTypeDescription.
private String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if(i > 0 && i <
s.length() - 1) {
ext = s.substring(i+1).toLowerCase();
}
return ext;
}
}
Adding a custom accessory
The final code example
we'll present in this article shows how to add a custom accessory
to the Swing file chooser:
class FilePreviewer extends
JComponent
implements PropertyChangeListener {
ImageIcon thumbnail = null;
File f = null;
public FilePreviewer(JFileChooser fc) {
setPreferredSize(new Dimension(100,
50));
fc.addPropertyChangeListener(this);
}
public void loadImage() {
if(f != null) {
ImageIcon tmpIcon
=
new ImageIcon(f.getPath());
if(tmpIcon.getIconWidth()
> 90) {
thumbnail = new ImageIcon(
tmpIcon.getImage().
getScaledInstance(90,
-1, Image.SCALE_DEFAULT));
} else {
thumbnail = tmpIcon;
}
}
}
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if(prop ==
JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)
{
f = (File) e.getNewValue();
if(isShowing())
{
loadImage();
repaint();
}
}
}
public void paint(Graphics g) {
if(thumbnail == null) {
loadImage();
}
if(thumbnail != null) {
int x = getWidth()/2
-
thumbnail.getIconWidth()/2;
int y = getHeight()/2
-
thumbnail.getIconHeight()/2;
if(y < 0) {
y = 0;
}
if(x < 5) {
x = 5;
}
thumbnail.paintIcon(this,
g, x, y);
}
}
}
Here are some
known bugs that still exist in the Swing file-chooser API:
- In the Java look and feel and the Windows L&F, the File
path ComboBox at the top of the file chooser currently does
not show the path associated with the file.
- When you select a directory and then clicking "Open,"
Swing doesn't open the directory you have chosen. Instead,
it returns the selected file.
- The setMultiSelectionEnabled()
method is currently ignored. This feature will be implemented
in a future Swing release.
- In the Windows look and feel, the List View option does not
show all the information that the native Windows L&F
file chooser does.
- Currently, the default dialog title is not being correctly set.
You can work around this bug by calling file
chooser.setDialogTitle(String title);
Jeff Dinkins is the Swing team member who is designing and developing
Swing's file-chooser dialogs.
|