12.2 The File Chooser Package


Under javax.swing, you'll find a package of helper classes for the JFileChooser. The javax.swing.filechooser package contains several classes for displaying and filtering files.

12.2.1 The FileFilter Class

The FileFilter class can be used to create filters for JFileChooser dialogs. The class contains only two abstract methods. It's important to note that extensions are not the only way to judge a file's fitness for a particular filter. The Mac filesystem, for example, can understand the creator of a file regardless of the file's name. On Unix systems, you might write a filter to display only files that are readable by the current user.

12.2.1.1 Constructor
public FileFilter( )

The FileFilter class receives this default constructor at compile time; it is not defined in the class itself.

12.2.1.2 Filter methods
public abstract boolean accept(File f)

Return true if file f matches this filter. Note that you must explicitly accept directories (f.isDirectory( ) == true) if you want to allow the user to navigate into any subfolders.

public abstract String getDescription( )

Return a short description to appear in the filters pulldown on the chooser. An example would be "Java Source Code" for any .java files.

Figure 12-5 shows a file chooser with custom filters for multimedia file types.

Figure 12-5. A custom set of filters for use with JFileChooser
figs/swng2.1205.gif

Here's the code for the application. Before we make this chooser visible, we create and insert the three new filters for our media types. Other than that, it's pretty much the same code as our previous applications. The Swing demos included in the SDK provide access to a similar extension-based file filter class. However, we use this example anyway, as it illustrates the inner workings of a filter that should seem familiar to most programmers.

// MyFilterChooser.java // Just a simple example to see what it takes to make one of these filters work // import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class MyFilterChooser extends JFrame {   public MyFilterChooser( ) {     super("Filter Test Frame");     setSize(350, 200);     setDefaultCloseOperation(EXIT_ON_CLOSE);     Container c = getContentPane( );     c.setLayout(new FlowLayout( ));          JButton openButton = new JButton("Open");     final JLabel statusbar = new JLabel("Output of your selection will go here");     openButton.addActionListener(new ActionListener( ) {       public void actionPerformed(ActionEvent ae) {         String[] pics = new String[] {"gif", "jpg", "tif"};         String[] audios = new String[] {"au", "aiff", "wav"};         JFileChooser chooser = new JFileChooser( );         chooser.addChoosableFileFilter(new SimpleFileFilter(pics,                                         "Images (*.gif, *.jpg, *.tif)"));         chooser.addChoosableFileFilter(new SimpleFileFilter(".MOV"));         chooser.addChoosableFileFilter(new SimpleFileFilter(audios,                                         "Sounds (*.aiff, *.au, *.wav)"));         int option = chooser.showOpenDialog(MyFilterChooser.this);         if (option == JFileChooser.APPROVE_OPTION) {           if (chooser.getSelectedFile( )!=null)              statusbar.setText("You chose " + chooser.getSelectedFile( ).getName( ));         }         else {           statusbar.setText("You canceled.");         }       }     });     c.add(openButton);     c.add(statusbar);     setVisible(true);   }   public static void main(String args[]) {     MyFilterChooser mfc = new MyFilterChooser( );   } }

Here's the implementation of the filter class. You pass in an extension (or list of extensions) and a description of the extension(s) to the constructor. If you don't supply a description, the constructor builds a simple one for you based on the extensions you passed in. The only real work this class does happens in the accept( ) method, where we look to see if the file presented matches one of the supplied extensions.

// SimpleFileFilter.java // A straightforward, extension-based example of a file filter. This should be // replaced by a "first class" Swing class in a later release of Swing. // import javax.swing.filechooser.*; import java.io.File; public class SimpleFileFilter extends FileFilter {   String[] extensions;   String description;   public SimpleFileFilter(String ext) {     this (new String[] {ext}, null);   }   public SimpleFileFilter(String[] exts, String descr) {     // Clone and lowercase the extensions     extensions = new String[exts.length];     for (int i = exts.length - 1; i >= 0; i--) {       extensions[i] = exts[i].toLowerCase( );     }     // Make sure we have a valid (if simplistic) description.     description = (descr == null ? exts[0] + " files" : descr);   }   public boolean accept(File f) {     // We always allow directories, regardless of their extensions.     if (f.isDirectory( )) { return true; }     // It's a regular file, so check the extension.     String name = f.getName( ).toLowerCase( );     for (int i = extensions.length - 1; i >= 0; i--) {       if (name.endsWith(extensions[i])) {         return true;       }     }     return false;   }   public String getDescription( ) { return description; } } 

12.2.2 The FileView Class

Another abstract helper class in the javax.swing.filechooser package is the FileView class. This class is implemented by the various L&Fs to supply icons and descriptions for the basic file and folder entries in the filesystem. While each L&F has a default implementation of this class, you can write your own and attach it to a file chooser to supply custom icons and descriptions for interesting types of files.

12.2.2.1 Constructor
public FileView( )

The FileView class has only this default constructor.

12.2.2.2 Methods

All of the methods for the FileView class are abstract and take one File as an argument. You fill in these methods to present a clean, consistent view of all files throughout the file chooser. Most custom views end up making decisions based on file information, such as the file's name or extension, before returning a result from these methods.

public abstract String getName(File f)

Return the name of file f. While it's quite easy to return f.getName( ), you might want to return an all-uppercase version or a cross-platform, CD-ROM-compliant (ISO 9660) name, etc.

public abstract String getDescription(File f)

Return a description of the file. The description could be a short abstract of the file's contents. Your file chooser might not necessarily display this information.

public abstract String getTypeDescription(File f)

Return a description of the type of the file, such as "Directory" or "Bitmap Image."

public abstract Icon getIcon(File f)

Return an icon appropriate for file f. This could be a folder icon, a file icon, or some specific icon based on other file information, such as its extension.

public abstract boolean isTraversable(File f)

Answer questions about whether a directory can be opened. For example, Unix and Windows NT/2000 can prevent users from accessing directories for which they don't have permission. You could check permissions and return false if the user is not allowed to open a given folder. Rather than get an error when trying to open the folder, the user doesn't get the chance to try.

Figure 12-6 is an example of a custom FileView that (slowly!) displays tiny representations of any .gif or .jpg files in the directory instead of the generic icons. Since it loads the real image and scales it, rather than storing some separate set of real icons, you shouldn't try this on your collection of 5,000 JPEG clip-art images. It's great for small directories, though. This example also relies on the MetalIconFactory, so it does not run (properly) under other L&Fs. To avoid this problem, we force the use of the Metal L&F in the main( ) method by setting the swing.defaultlaf system property.

Figure 12-6. A custom file view for a file chooser that displays icons of image files
figs/swng2.1206.gif

Following is the code for this particular file view. Look at the getIcon( ) method. That's where we decide which icon to return for a particular file. In this implementation, we list all directories as traversable and return a rather generic type description for our files. Notice that in the getName( ) method we check for an empty string. On Windows platforms, this empty string corresponds to one of the drive letters. The "name" of the file is empty, but the path contains the appropriate information, so we return that. If you're curious about the MetalIconFactory that we use to get the file and folder icons, check out Chapter 26.

You might notice that we store a Component object (rather than JComponent) as our image observer. The reason for this is twofold. First, that's one class the createImage( ) method is defined in. Second, one obvious choice for the observer is the frame containing the application, which is frequently a JFrame, and JFrame does not descend from JComponent.

// ThumbNailFileView.java // A simple implementation of the FileView class that provides a 16 x 16 image of // each GIF or JPG file for its icon. This could be SLOW for large images, as we // simply load the real image and then scale it. // import java.io.File; import java.awt.*; import javax.swing.*; import javax.swing.filechooser.*; import javax.swing.plaf.metal.MetalIconFactory; public class ThumbNailFileView extends FileView {   private Icon fileIcon = MetalIconFactory.getTreeLeafIcon( );   private Icon folderIcon = MetalIconFactory.getTreeFolderIcon( );   private Component observer;   public ThumbNailFileView(Component c) {     // We need a component to create our icon's image.     observer = c;   }   public String getDescription(File f) {     // We won't store individual descriptions, so just return the     // type description.     return getTypeDescription(f);   }   public Icon getIcon(File f) {     // Is it a folder?     if (f.isDirectory( )) { return folderIcon; }     // It's a file, so return a custom icon if it's an image file.     String name = f.getName( ).toLowerCase( );     if (name.endsWith(".jpg") || name.endsWith(".gif")) {       return new Icon16(f.getAbsolutePath( ));     }     // Return the generic file icon if it's not.     return fileIcon;   }   public String getName(File f) {     String name = f.getName( );     return name.equals("") ? f.getPath( ) : name;   }   public String getTypeDescription(File f) {     String name = f.getName( ).toLowerCase( );     if (f.isDirectory( )) { return "Folder"; }     if (name.endsWith(".jpg")) { return "JPEG Image"; }     if (name.endsWith(".gif")) { return "GIF Image"; }     return "Generic File";   }   public Boolean isTraversable(File f) {     // We'll mark all directories as traversable.     return f.isDirectory( ) ? Boolean.TRUE : Boolean.FALSE;   }   public class Icon16 extends ImageIcon {     public Icon16(String f) {        super(f);       Image i = observer.createImage(16, 16);       i.getGraphics( ).drawImage(getImage( ), 0, 0, 16, 16, observer);       setImage(i);     }     public int getIconHeight( ) { return 16; }     public int getIconWidth( ) { return 16; }          public void paintIcon(Component c, Graphics g, int x, int y) {       g.drawImage(getImage( ), x, y, c);     }   } }

Here's the application that uses this file view implementation. The only real change from the previous applications is in the properties we set for the chooser and our forced use of the Metal L&F.

// MyViewChooser.java // A simple example to see what it takes to make one of these FileViews work // import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class MyViewChooser extends JFrame {   JFrame parent;   public MyViewChooser( ) {     super("File View Test Frame");     setSize(350, 200);     setDefaultCloseOperation(EXIT_ON_CLOSE);     parent = this;     Container c = getContentPane( );     c.setLayout(new FlowLayout( ));          JButton openButton = new JButton("Open");     final JLabel statusbar = new JLabel("Output of your selection will go here");     openButton.addActionListener(new ActionListener( ) {       public void actionPerformed(ActionEvent ae) {         JFileChooser chooser = new JFileChooser( );         // Set up our own file view for the chooser.         chooser.setFileView(new ThumbNailFileView(MyViewChooser.this));         int option = chooser.showOpenDialog(parent);         if (option == JFileChooser.APPROVE_OPTION) {           statusbar.setText("You chose " + chooser.getSelectedFile( ).getName( ));         }         else {           statusbar.setText("You cancelled.");         }       }     });     c.add(openButton);     c.add(statusbar);   }   public static void main(String args[]) {     System.setProperty("swing.defaultlaf",                         "javax.swing.plaf.metal.MetalLookAndFeel");     MyViewChooser vc = new MyViewChooser( );     vc.setVisible(true);   } } 

12.2.3 The FileSystemView Class

Another detail missing from the normal FileChooser dialog is a system-independent way of asking for a look at the entire filesystem. On Windows machines, for example, there are several "root" directories one for each floppy drive, hard drive, CD drive, etc. On Unix systems (which includes Mac OS X), there is only one root directory, named "/". The abstract FileSystemView class is meant to be a source for system-independent views that map nicely to the real filesystem underneath your application. Currently, both Unix and Win32 systems have real implementations, and others are planned for release. (MacOS X relies on a Unix view of things.) Systems that do not have a full implementation use a generic filesystem view, similar to what is available through the standard java.io.File class.

12.2.3.1 Class instantiation method
public static FileSystemView getFileSystemView( )

The default implementation checks the file separator character to decide which filesystem view to return. A / returns a Unix view, \ returns a Win32 view, and everything else gets the generic view.

12.2.3.2 File and folder methods

If you do plan to build your own filesystem view, the following methods are the key pieces to look at:

public abstract File createNewFolder(File containingDir) throws IOException

Create a new folder with some default name appropriate to the filesystem.

public File[] getFiles(File dir, boolean useFileHiding)

Return a list of all of the files in dir. If useFileHiding is true, each file in dir is checked with isHiddenFile( ) before being added to the list.

public File[] getRoots( )

Return a list of "root" directories. On Unix or Mac OS X systems, this is the / directory. On Windows machines, this is a list of the active drive letters. In OS X, secondary partitions (including mounted removable media) are listed in the /Volumes directory. Users are accustomed to thinking of these as separate entities, so you might want to add your own code to include them as separate "roots."

public boolean isHiddenFile(File f)

Return true if file f is a hidden file. What makes a file a hidden file differs from system to system.

public boolean isRoot(File f)

Return true if file f maps to a root directory.



Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net