[an error occurred while processing this directive]
The Morgue Commentary PLAF Papers Friends Tech Topics Swing Text The Web Tech Topics What's Swing?
Index Archive Call 911 PLAF Papers Friends Tech Topics Swing Text Swing & the Web IDE Roundup Special Report Databank Page 2 Page One What's Swing?
JDK Docs Download JDK Swing API Docs Download Swing Java Tutorial
The Swing Connection The Archive Tech Topics

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:

bar_purple_520 

    Downloading the examples

    Source code graphicA 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.

bar_purple_520 

File-chooser basics 

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

bar_purple_520 

    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.

bar_purple_520 

The JFileChooser API 

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:

Customized chooser screen shot 

  • Settable user-chooseable file filters, as shown below:

Settable-filter chooser screen shot 

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

Custom accessories chooser screen shot 

  • 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:

  1. 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.
     
  2. 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.

 

The file chooser in depth 

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

bar_purple_520 

    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.
     

bar_purple_520 

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

 

Known major bugs 

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.

[an error occurred while processing this directive]