Home > Articles

Exploring JFileChooser and JColorChooser

  • Print
  • + Share This
  • 💬 Discuss
Get an introduction to two Swing chooser components. Swing's JFileChooser and JColorChooser are vital to graphic user interfaces, and in this chapter, you will learn how you can make them work for you.

This chapter discusses two Swing chooser components—JFileChooser and JColorChooser—that are used to select files and colors, respectively.

JFileChooser

File choosers, like option panes—see "JOptionPane" on page 815—are lightweight components that are meant to be placed in a dialog. Once an instance of JFileChooser has been instantiated, it can be added to a dialog. Additionally, the JFileChooser class provides methods that add an existing file chooser to a modal dialog and display the dialog. The methods return an integer value indicating whether the chooser's approve button was activated or the dialog was dismissed.

File choosers support three display modes: files only, directories only, and files and directories. Additionally file choosers support both single and multiple selection.1

File choosers can be customized in a number of different ways, as Figure 16-1 illustrates. The top picture in Figure 16-1 shows the standard dialog displayed as a result of invoking JFileChooser.showSaveDialog(). The bottom picture in Figure 16-1 shows a file chooser with customized text for the dialog title, approve button and its tooltip, custom filters, custom icons, and an accessory component.

Figure 16-1Figure 16-1 Customizing File Choosers


File chooser features are summarized in Feature Summary 16-1.

Feature Summary 16-1 JFileChooser

Open/Save/Custom Dialogs

JFileChooser provides three methods that display a modal dialog containing choosers: showOpenDialog(), showSaveDialog(), and showDialog().2 Each of the methods sets the dialog title and the string displayed in the file chooser's approve button and returns an integer value indicating whether the approve button was activated or the dialog was canceled.

Display Modes

JFileChooser supports three display modes: files only, directories only, and files and directories.

Multiple Selection

File choosers come with both single and multiple selection; however, multiple selection is not fully supported in Swing 1.1.

Approve Button

Three facets of a file chooser's approve button can be customized: the button's text, its tooltip text, and mnemonic.

File Filters

Specific files or types of files can be filtered from a file chooser. File choosers can have multiple filters, but only one is active at any given time.

File Views

Given a file, the icons and file names displayed in a file chooser are obtained from a file view—an object that extends the FileView class. File choosers can be fitted with custom file views.

Accessory Component

A component can be installed in a file chooser for any number of purposes. Previewers for specific types of files—such as image previewers—represent one use for accessory components.

Figure 16-2 shows an application that displays a file dialog. After the dialog is dismissed, a message dialog communicates the selected file (or lack thereof). The top picture in Figure 16-2 shows the application as it appears initially, and the middle picture shows the file chooser displayed as a result of activation of the application's button. The bottom picture shows the message dialog displayed after a file has been selected.

Figure 16-2Figure 16-2 A Simple File Chooser Example


The application creates a button that is added to the application frame's content pane. The application also creates a file chooser with the JFileChooser no-argument constructor.

When the button contained in the application is activated, JFileChooser.showOpenDialog() is invoked to display the file chooser in a modal dialog. Because the dialog is modal, the call to showOpenDialog() does not return until the dialog is dismissed.

After the dialog is dismissed, JFileChooser.getSelectedFile() obtains a reference to the file that was selected in the file chooser. Subsequently, a message dialog is displayed that indicates whether the chooser's approve button was activated or the dialog was canceled, depending upon the value returned from JFileChooser.showOpenDialog().

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Simple File Chooser Application");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File file = chooser.getSelectedFile();

        if(file != null &&
          state == JFileChooser.APPROVE_OPTION) {
          JOptionPane.showMessageDialog(
                      null, file.getPath());
        }
        else if(state == JFileChooser.CANCEL_OPTION) {
          JOptionPane.showMessageDialog(
                      null, "Canceled");
        }
      }
    });
  }

The application shown in Figure 16-2 is listed in its entirety in Example 16-1.

Example 16-1 A Simple File Chooser Example

import java.awt.*;

import java.awt.event.*;
import java.io.File;
import javax.swing.*;

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Simple File Chooser Application");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File file = chooser.getSelectedFile();

        if(file != null &&
          state == JFileChooser.APPROVE_OPTION) {
          JOptionPane.showMessageDialog(
                      null, file.getPath());
        }
        else if(state == JFileChooser.CANCEL_OPTION) {
          JOptionPane.showMessageDialog(
                      null, "Canceled");
        }
      }
    });
  }
  public static void main(String args[]) {
    JFrame f = new Test();
    f.setBounds(300,300,350,100);
    f.setVisible(true);

    f.setDefaultCloseOperation(
      WindowConstants.DISPOSE_ON_CLOSE);
  
    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);  
      }
    });
  }
} 

TIP

Check for null Selected Files

If a file chooser's approve button is activated without a file being selected, the file returned from JFileChooser.getSelectedFile() will be null. As a result, before a file returned from JFileChooser.getSelectedFile() is used, a check should be made to ensure that a file has actually been selected.

For example, the application listed in Example 16-1 makes the following check:

button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    int state = chooser.showOpenDialog(null);
    File file = chooser.getSelectedFile();

    if(file != null && state == JFileChooser.APPROVE_OPTION) 
      JOptionPane.showMessageDialog(null, file.getPath());
		...
  ...
}

In other words, just because a JFileChooser.show...() method returns JFileChooser.APPROVE_OPTION does not necessarily mean that a file was selected.

File Chooser Types

The JFileChooser class supports three types of preconfigured file choosers and associated dialogs—custom, open, and save—that are differentiated by the dialog title and the text used for the file chooser's approve button.

JFileChooser dialog types are listed in Table 16-1, along with the JFileChooser instance methods used to show the dialogs.

Table 16-1 JFileChooser Dialog Types

Dialog Type

Method Used to Show Dialog

Dialog Title / Approve Button Text

Custom

int showDialog(Component parent,

 

String approveButtonText)

Specified by second argument

 

Open

int showOpenDialog(Component parent)

Open

Save

int showSaveDialog(Component parent)

Save


The methods listed in Table 16-1 display a modal dialog containing a file chooser and return an integer value after the dialog has been dismissed, signifying whether the chooser's approve button was activated or the dialog was canceled. The dialog is centered over the parent component that is passed to the methods. If the methods are passed a null value for the parent component, the dialog is centered on the screen.

The following constants are returned from the methods listed in Table 16-1.

JFileChooser.APPROVE_OPTION

JFileChooser.CANCEL_OPTION

The first method listed in Table 16-1 is passed a string that is used as the text for the file chooser's approve button and the dialog's title. The last two methods listed in Table 16-1 set the dialog title and the file chooser's approve button text to "Open" and "Save", respectively.

Figure 16-3 shows an application that uses the methods listed above to display a file chooser in a modal dialog. The application contains a combo box that allows the type of file chooser to be displayed and a button that displays the dialog. The top pictures in Figure 16-3 show a "Save" file chooser, and the middle pictures show an "Open" file chooser. The bottom pictures show a custom file chooser whose approve button text and dialog title are specified with an input dialog.

Figure 16-3Figure 16-3 Default File Chooser Types


The application creates a file chooser, a combo box, and a button; the combo box and button are subsequently added to the application frame's content pane. When the button is activated, the file chooser is displayed in either an open, save, or custom dialog, depending upon the value selected from the combo box. After the dialog has been dismissed, a message dialog is displayed that indicates whether a file was selected or the dialog was canceled.

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JComboBox comboBox = new JComboBox();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Standard File Chooser Types");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(comboBox);
    contentPane.add(button);    

    comboBox.addItem("OPEN_DIALOG");
    comboBox.addItem("SAVE_DIALOG");
    comboBox.addItem("custom dialog");

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String message = "CANCELED";
        int state = showChooser(
              (String)comboBox.getSelectedItem());
        File file = chooser.getSelectedFile();

        if(file != null &&
           state == JFileChooser.APPROVE_OPTION) {
          message = chooser.getApproveButtonText() + 
               " " + file.getPath();
        }
        JOptionPane.showMessageDialog(null, message);
      }
    });
  }

The application's showChooser method is passed the string selected in the combo box and displays an appropriate file chooser dialog. If custom dialog was selected from the combo box, an input dialog is displayed to obtain the string used for the file chooser's approve button text and the dialog's title.

  private int showChooser(String s) {
    int state; 

    if(s.equals("OPEN_DIALOG")) {
      state = chooser.showOpenDialog(null);
    }
    else if(s.equals("SAVE_DIALOG")) {
      state = chooser.showSaveDialog(null);
    }
    else { // custom dialog
      String string = JOptionPane.showInputDialog(
                    null, 
                    "Button/Title String:");

      chooser.setApproveButtonMnemonic(string.charAt(1));
      state = chooser.showDialog(Test.this, string);
    }
    return state;
  }

The application shown in Figure 16-3 is listed in its entirety in Example 16-2.

Example 16-2 Default File Chooser Types

import java.awt.*;

import java.awt.event.*;
import java.io.File;
import javax.swing.*;

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JComboBox comboBox = new JComboBox();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Standard File Chooser Types");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(comboBox);
    contentPane.add(button);    

    comboBox.addItem("OPEN_DIALOG");
    comboBox.addItem("SAVE_DIALOG");
    comboBox.addItem("custom dialog");

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String message = "CANCELED";
        int state = showChooser(
              (String)comboBox.getSelectedItem());
        File file = chooser.getSelectedFile();

        if(file != null &&
           state == JFileChooser.APPROVE_OPTION) {
          message = chooser.getApproveButtonText() + 
               " " + file.getPath();
        }
        JOptionPane.showMessageDialog(null, message);
      }
    });
  }
  private int showChooser(String s) {
    int state; 

    if(s.equals("OPEN_DIALOG")) {
      state = chooser.showOpenDialog(null);
    }
    else if(s.equals("SAVE_DIALOG")) {
      state = chooser.showSaveDialog(null);
    }
    else { // custom dialog
      String string = JOptionPane.showInputDialog(
                    null, 
                    "Button/Title String:");

      chooser.setApproveButtonMnemonic(string.charAt(1));
      state = chooser.showDialog(Test.this, string);
    }
    return state;
  }
  public static void main(String args[]) {
    JFrame f = new Test();
    f.setBounds(300,300,350,100);
    f.setVisible(true);

    f.setDefaultCloseOperation(
      WindowConstants.DISPOSE_ON_CLOSE);
  
    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);  
      }
    });
  }
}

Accessory Components

File choosers can accommodate an accessory component, as illustrated in Figure 16-4. The accessory component is placed to the right of the file listing area3 and is sized as tall as the file listing area and as wide as the accessory component's preferred width. Accessory components can be used for any purpose, the most common of which is a previewer that allows the content of files to be displayed as files are selected in the file chooser.

Figure 16-4Figure 16-4 An Image Previewer Accessory

Figure 16-4 shows a file chooser equipped with an image previewer accessory component. When a GIF or JPEG file is selected, the image previewer displays a scaled version of the image.

The application shown in Figure 16-4 implements an ImagePreviewer class that extends JLabel. When a file is selected in the file chooser, ImagePreviewer.configure() is passed a reference to the selected file. The image displayed in the previewer is an image icon created with the selected file's path.

After the image icon is created, its image is reset to a scaled version of the image by invocation of Image.getScaledInstance(). The scaled version of the image is used to create another image icon that is used as the label's icon.

  class ImagePreviewer extends JLabel {
    public void configure(File f) {
      Dimension size = getSize();
      Insets insets = getInsets();

      // used to create full-size image
      ImageIcon icon = new ImageIcon(f.getPath());

      // set label's icon to new image icon 
      // with scaled image
      setIcon(
       new ImageIcon(icon.getImage().getScaledInstance(
            size.width - insets.left - insets.right, 
            size.height - insets.top - insets.bottom, 
            Image.SCALE_SMOOTH)));
      ...
    }
    ...
  }

Note: The configure method could create the original image by hand, thereby eliminating the need for a second image icon, but the implementation presented here is more readable.

The image previewer is placed in an instance of PreviewPanel, which is an extension of JPanel. The PreviewPanel class sets its preferred size to a dimension of (150,0) because the preferred height of accessory components is ignored.4

The PreviewPanel class also sets its border to an etched border and adds the previewer as its center component. A label that identifies the previewer is specified as the preview panel's north component.

  class PreviewPanel extends JPanel {
    public PreviewPanel() {
      JLabel label = new JLabel("Image Previewer",
                    SwingConstants.CENTER);
      setPreferredSize(new Dimension(150,0));
      setBorder(BorderFactory.createEtchedBorder());

      setLayout(new BorderLayout());

      label.setBorder(BorderFactory.createEtchedBorder());
      add(label, BorderLayout.NORTH);
      add(previewer, BorderLayout.CENTER);
    }
    ...
  }

The application creates a button, file chooser, image previewer, and preview panel. The button is added to the application frame's content pane, and the preview panel is specified as the file chooser's accessory component by invocation of JFileChooser.setAccessory().

public class Test extends JFrame {
  JFileChooser  chooser = new JFileChooser();
  ImagePreviewer previewer = new ImagePreviewer();
  PreviewPanel  previewPanel = new PreviewPanel();
  ...

  public Test() {
    super("Image Previewer Accessory");
    
    Container contentPane = getContentPane();
    JButton   button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setAccessory(previewPanel);
    ...

An action listener that invokes JFileChooser.showOpenDialog() is added to the button. Subsequently, a message dialog is displayed indicating whether a file was selected or the dialog was canceled.

    ...
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File file = chooser.getSelectedFile();
        String s = "CANCELED";

        if(file != null && 
           state == JFileChooser.APPROVE_OPTION) {
          s = "File Selected: " + file.getPath();
        }
        JOptionPane.showMessageDialog(null, s);
      }
    });
    ...

A property change listener that reacts to file selections is added to the file chooser. If the selected file has a suffix of ".gif" or ".jpg", the previewer is configured by invocation of ImagePreviewer.configure().

    ...
    chooser.addPropertyChangeListener(
                  new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if(e.getPropertyName().equals(
          JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
           File f = (File)e.getNewValue();
          String s = f.getPath(), suffix = null;
          int i = s.lastIndexOf('.'); 

            if(i > 0 && i < s.length() - 1)
              suffix = s.substring(i+1).toLowerCase();

          if(suffix.equals("gif") || 
            suffix.equals("jpg"))
            previewer.configure(f);
        }
      }
    });
  }
  ...
}

The application shown in Figure 16-4 is listed in its entirety in Example 16-3.

Example 16-3 An Image Previewer Accessory

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;

public class Test extends JFrame {
  JFileChooser  chooser = new JFileChooser();
  ImagePreviewer previewer = new ImagePreviewer();
  PreviewPanel  previewPanel = new PreviewPanel();

  class PreviewPanel extends JPanel {
    public PreviewPanel() {
      JLabel label = new JLabel("Image Previewer",
                    SwingConstants.CENTER);
      setPreferredSize(new Dimension(150,0));
      setBorder(BorderFactory.createEtchedBorder());

      setLayout(new BorderLayout());

      label.setBorder(BorderFactory.createEtchedBorder());
      add(label, BorderLayout.NORTH);
      add(previewer, BorderLayout.CENTER);
    }
  }
  public Test() {
    super("Image Previewer Accessory");
    
    Container contentPane = getContentPane();
    JButton  button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setAccessory(previewPanel);


    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File file = chooser.getSelectedFile();
        String s = "CANCELED";

        if(file != null && 
           state == JFileChooser.APPROVE_OPTION) {
          s = "File Selected: " + file.getPath();
        }
        JOptionPane.showMessageDialog(null, s);
      }
    });

    chooser.addPropertyChangeListener(
                  new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if(e.getPropertyName().equals(
          JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
          File f = (File)e.getNewValue();
          String s = f.getPath(), suffix = null;
          int i = s.lastIndexOf('.'); 

          if(i > 0 && i < s.length() - 1)
            suffix = s.substring(i+1).toLowerCase();

          if(suffix.equals("gif") || 
            suffix.equals("jpg"))
            previewer.configure(f);
        }
      }
    });
  }
  public static void main(String a[]) {
    JFrame f = new Test();
    f.setBounds(300, 300, 300, 75);
    f.setVisible(true);

    f.setDefaultCloseOperation(
                WindowConstants.DISPOSE_ON_CLOSE);

    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
class ImagePreviewer extends JLabel {
  public void configure(File f) {
    Dimension size = getSize();
    Insets insets = getInsets();
    ImageIcon icon = new ImageIcon(f.getPath());

    setIcon(new ImageIcon(icon.getImage().getScaledInstance(
            size.width - insets.left - insets.right, 
            size.height - insets.top - insets.bottom, 
            Image.SCALE_SMOOTH)));
  }
}

Filtering File Types

Files that fit a certain criteria, such as files that end with ".gif", can be filtered out of a file chooser with a file filter. Any number of filters can be associated with a single file chooser, but only one of the filters can be active at any given time.

By default, file choosers are fitted with a single "accept all" filter, that, as its name suggests, accepts all files. The default filter can be replaced with a custom filter by invocation of JFileChooser.setFileFilter(), which replaces the current filter.

File filters are implemented by extension of the abstract swing.filechooser.FileFilter class, which is summarized in Class Summary 15-5.

Class Summary 15-5 fileFilter

Extends: java.lang.Object

Constructors

public FileFilter()

The no-argument constructor is compiler generated.

Methods

public abstract boolean accept(File)
public abstract String getDescription()

The accept method returns a boolean value indicating whether a particular file is accepted by a filter. The getDescription method returns a short description of the types of files that a filter accepts. The description is displayed in the file filter combo box.5

The file chooser shown in Figure 16-5 has a text file filter that accepts only files ending in ".txt". The file chooser is also fitted with a text previewer, which is listed in Example 16-4 but not discussed.

Figure 16-5Figure 16-5 A Text File Filter and Previewer

The file chooser shown in Figure 16-5 is created by the application listed below, which sets the file filter for the chooser with the JFileChooser.setFileFilter method.

public class Test extends JFrame {
  JFileChooser  chooser = new JFileChooser();
  TextPreviewer previewer = new TextPreviewer();
  PreviewPanel  previewPanel = new PreviewPanel();

  ...
  public Test() {
    super("Filtering Files");
    
    Container contentPane = getContentPane();
    JButton  button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setAccessory(previewPanel);
    chooser.setFileFilter(new TextFilter());

  ...
  }
}

The TextFilter class extends FileFilter and accepts only files that end in ".txt". The description is used in the file chooser's file filter combo box, as can be seen from Figure 16-5.

class TextFilter 
        extends javax.swing.filechooser.FileFilter {
  public boolean accept(File f) {
    boolean accept = f.isDirectory();

    if( ! accept) {
      String suffix = getSuffix(f);

      if(suffix != null) 
        accept = suffix.equals("txt");
    }
    return accept;
  }
  public String getDescription() {
    return "Text Files(*.txt)";
  }
  private String getSuffix(File f) {
    String s = f.getPath(), suffix = null;
    int i = s.lastIndexOf('.');

    if(i > 0 && i < s.length() - 1)
      suffix = s.substring(i+1).toLowerCase();

    return suffix;
  }
}

The application shown in Figure 16-5 is listed in its entirety in Example 16-4.

Example 16-4 A Text File Filter and Previewer

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.URL;

public class Test extends JFrame {
  JFileChooser  chooser = new JFileChooser();
  TextPreviewer previewer = new TextPreviewer();
  PreviewPanel  previewPanel = new PreviewPanel();

  class PreviewPanel extends JPanel {
    public PreviewPanel() {
      JLabel label = new JLabel("Text Previewer",
                    SwingConstants.CENTER);
      setPreferredSize(new Dimension(350,0));
      setBorder(BorderFactory.createEtchedBorder());

      setLayout(new BorderLayout());

      label.setBorder(BorderFactory.createEtchedBorder());
      add(label, BorderLayout.NORTH);
      add(previewer, BorderLayout.CENTER);
    }
  }
  public Test() {
    super("Filtering Files");
    
    Container contentPane = getContentPane();
    JButton  button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File file = chooser.getSelectedFile();
        String s = "CANCELED";

        if(file != null &&
          state == JFileChooser.APPROVE_OPTION) {
          s = "File Selected: " + file.getPath();
        }
        JOptionPane.showMessageDialog(null, s);
      }

    });

    chooser.setAccessory(previewPanel);
    chooser.setFileFilter(new TextFilter());

    chooser.addPropertyChangeListener(
                  new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if(e.getPropertyName().equals(
          JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
          previewer.configure((File)e.getNewValue());
        }
      }
    });
  }
  public static void main(String a[]) {
    JFrame f = new Test();
    f.setBounds(300, 300, 300, 75);
    f.setVisible(true);

    f.setDefaultCloseOperation(
                WindowConstants.DISPOSE_ON_CLOSE);

    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
class TextFilter 
        extends javax.swing.filechooser.FileFilter {
  public boolean accept(File f) {
    boolean accept = f.isDirectory();

    if( ! accept) {
      String suffix = getSuffix(f);

      if(suffix != null) 
        accept = suffix.equals("txt");
    }
    return accept;
  }
  public String getDescription() {
    return "Text Files(*.txt)";
  }
  private String getSuffix(File f) {
    String s = f.getPath(), suffix = null;
    int i = s.lastIndexOf('.');

    if(i > 0 && i < s.length() - 1)
      suffix = s.substring(i+1).toLowerCase();

    return suffix;
  }
}
class TextPreviewer extends JComponent {
  private JTextArea textArea = new JTextArea();
  private JScrollPane scrollPane = new JScrollPane(textArea);

  public TextPreviewer() {
    textArea.setEditable(false);

    setBorder(BorderFactory.createEtchedBorder());
    setLayout(new BorderLayout());
    add(scrollPane, BorderLayout.CENTER);
  }
  public void configure(File file) {
    textArea.setText(contentsOfFile(file));

    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JViewport vp = scrollPane.getViewport();

        vp.setViewPosition(new Point(0,0));
      }
    });
  }
  public static String contentsOfFile(File file) {
    String s = new String();
    char[] buff = new char[50000];
    InputStream is;
    InputStreamReader reader;
    URL url;

    try {
      reader = new FileReader(file);

      int nch;

      while ((
        nch = reader.read(buff, 0, buff.length)) != -1) {
        s = s + new String(buff, 0, nch);
      }
    } 
    catch (java.io.IOException ex) {
      s = "Could not load file";
    }
    return s;
  }
}

Choosable Filters

As illustrated in "Filtering File Types" on page 936, JFileChooser.setFileFilter() replaces the default file filter with the filter that is passed to the method. If it is desirable to equip a file chooser with multiple filters, the JFileChooser.addChoosableFilter method can be used to add a filter to the current list of filters. The current list of filters can be accessed, and filters can be removed with the JFileChooser methods getChoosableFilters() and removeChoosableFilter(), respectively.

Figure 16-6 shows a file chooser with three filters, one for text files, another for Java source code files, and the default filter that accepts all files. The file chooser is also equipped with a text previewer, which is listed in Example 16-5 but not discussed.6

Figure 16-6Figure 16-6 Multiple File Filters

The application that shows the file chooser in Figure 16-6 creates an instance of JFileChooser and invokes JFileChooser.addChoosableFileFilter to add the text and Java code filters.

  public Test() {
     JFileChooser  chooser = new JFileChooser();
    TextPreviewer previewer = new TextPreviewer();
    PreviewPanel  previewPanel = new PreviewPanel();

    super("Filtering Files");
    
    Container contentPane = getContentPane();
    JButton  button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setAccessory(previewPanel);
    chooser.addChoosableFileFilter(new TextFilter());
    chooser.addChoosableFileFilter(new JavaCodeFilter());
    ...
  }

Because both filters determine the acceptability of files according to file name suffix, the filters extend a filter that is suffix aware. The SuffixAwareFilter is an abstract filter that accepts all directories and provides a method that returns a file name suffix, given a file. The SuffixAwareFilter is abstract because it leaves the getDescription method for subclasses to implement.

  ...
  abstract class SuffixAwareFilter 
        extends javax.swing.filechooser.FileFilter {
  public String getSuffix(File f) {
    String s = f.getPath(), suffix = null;
    int i = s.lastIndexOf('.');

    if(i > 0 && i < s.length() - 1)
      suffix = s.substring(i+1).toLowerCase();

    return suffix;
  }
  public boolean accept(File f) {
    return f.isDirectory();
  }
}
...

Both TextFilter and JavaCodeFilter will accept a file if it is accepted by the SuffixAwareFilter superclass (which means the file is a directory) or the file's suffix matches ".txt" or ".java", respectively.

...
class JavaCodeFilter extends SuffixAwareFilter {
  public boolean accept(File f) {
    boolean accept = super.accept(f);

    if( ! accept) {
      String suffix = getSuffix(f);

      if(suffix != null)
        accept = super.accept(f) || suffix.equals("java");
    }
    return accept;
  }
  public String getDescription() {
    return "Java Source Code Files(*.java)";
  }
}
class TextFilter extends SuffixAwareFilter {
  public boolean accept(File f) {
    String suffix = getSuffix(f);

    if(suffix != null)
      return super.accept(f) || suffix.equals("txt");

    return false;
  }
  public String getDescription() {
    return "Text Files(*.txt)";
  }
}

The application shown in Figure 16-6 is listed in its entirety in Example 16-5.

Example 16-5 Multiple File Filters

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.URL;

public class Test extends JFrame {
  JFileChooser  chooser = new JFileChooser();
  TextPreviewer previewer = new TextPreviewer();
  PreviewPanel  previewPanel = new PreviewPanel();

  class PreviewPanel extends JPanel {
    public PreviewPanel() {
      JLabel label = new JLabel("Text Previewer",
                    SwingConstants.CENTER);
      setPreferredSize(new Dimension(350,0));
      setBorder(BorderFactory.createEtchedBorder());

      setLayout(new BorderLayout());

      label.setBorder(BorderFactory.createEtchedBorder());
      add(label, BorderLayout.NORTH);
      add(previewer, BorderLayout.CENTER);
    }
  }
  public Test() {
    super("Filtering Files");
    
    Container contentPane = getContentPane();
    JButton  button = new JButton("Select A File");

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setAccessory(previewPanel);
    chooser.addChoosableFileFilter(new TextFilter());
    chooser.addChoosableFileFilter(new JavaCodeFilter());

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        String s = "CANCELED";

        if(state == JFileChooser.APPROVE_OPTION) {
          s = "File Selected: " + 
             chooser.getSelectedFile().getPath();
        }
        JOptionPane.showMessageDialog(null, s);
      }
    });

    chooser.addPropertyChangeListener(
                  new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        if(e.getPropertyName().equals(
          JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
          previewer.configure((File)e.getNewValue());
        }
      }
    });
  }
  public static void main(String a[]) {
    JFrame f = new Test();
    f.setBounds(300, 300, 300, 75);
    f.setVisible(true);

    f.setDefaultCloseOperation(
                WindowConstants.DISPOSE_ON_CLOSE);

    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
abstract class SuffixAwareFilter 
        extends javax.swing.filechooser.FileFilter {
  public String getSuffix(File f) {
    String s = f.getPath(), suffix = null;
    int i = s.lastIndexOf('.');

    if(i > 0 && i < s.length() - 1)
      suffix = s.substring(i+1).toLowerCase();

    return suffix;
  }
  public boolean accept(File f) {
    return f.isDirectory();
  }
}
class JavaCodeFilter extends SuffixAwareFilter {
  public boolean accept(File f) {
    boolean accept = super.accept(f);

    if( ! accept) {
      String suffix = getSuffix(f);

      if(suffix != null)
        accept = super.accept(f) || suffix.equals("java");
    }
    return accept;
  }
  public String getDescription() {
    return "Java Source Code Files(*.java)";
  }
}
class TextFilter extends SuffixAwareFilter {
  public boolean accept(File f) {
    String suffix = getSuffix(f);

    if(suffix != null)
      return super.accept(f) || suffix.equals("txt");

    return false;
  }
  public String getDescription() {
    return "Text Files(*.txt)";
  }
}
class TextPreviewer extends JComponent {
  private JTextArea textArea = new JTextArea();
  private JScrollPane scrollPane = new JScrollPane(textArea);

  public TextPreviewer() {
    textArea.setEditable(false);

    setBorder(BorderFactory.createEtchedBorder());
    setLayout(new BorderLayout());
    add(scrollPane, BorderLayout.CENTER);
  }
  public void configure(File file) {
    textArea.setText(contentsOfFile(file));

    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JViewport vp = scrollPane.getViewport();

        vp.setViewPosition(new Point(0,0));
      }
    });
  }
  static String contentsOfFile(File file) {
    String s = new String();
    char[] buff = new char[50000];
    InputStream is;
    InputStreamReader reader;
    URL url;

    try {
      reader = new FileReader(file);

      int nch;

      while ((
        nch = reader.read(buff, 0, buff.length)) != -1) {
        s = s + new String(buff, 0, nch);
      }
    } 
    catch (java.io.IOException ex) {
      s = "Could not load file";
    }
    return s;
  }
} 

TIP

Choosable File Filters

File filters for file choosers can be accessed by the following methods:

void setFileFilter(swing.filechooser.FileFilter)
void addChoosableFileFilter(swing.filechooser.FileFilter)
void removeChoosableFileFilter(swing.filechooser.FileFilter)
swing.filechooser.FileFilter getChoosableFileFilters()

The use of the word choosable is unfortunate,7 because it implies that the filter set by setFileFilter() is somehow not choosable. In actuality, all of the methods listed above pertain to a file chooser's choosable file filters.

File Views

File choosers obtain the icons and file names they display from an object that is an extension of the abstract swing.filechooser.FileView class. The default file view is implemented by the BasicFileChooserUI.BasicFileView class, but it can be wholly or partially replaced if a file view is explicitly set with the JFileChooser.setFileView method.

If a file chooser is explicitly fitted with a file view that returns null from any of its methods, the default file view is queried for the information. For example, if a file chooser has a file view that returns null from the getName method, the name is obtained from an instance of BasicFileView. Therefore, default file view behavior can be partially overridden.

The swing.filechooser.FileView class is summarized in Class Summary 15-6.

Class Summary 15-6 FileView

Extends: java.lang.Object

Constructors

public FileView()

The FileView constructor is compiler generated, because no constructors are implemented by the FileView class.

Methods

Icon / Name / Is Traversable

public abstract Icon getIcon(File)
public abstract String getName(File)
public abstract Boolean isTraversable(File)

The first two methods listed above return an icon and a string respectively, given a file. The icon and string represent files in a file chooser.

The isTraversable method indicates whether a file (typically a directory) can be opened. For example, implementing an extension of FileView that returns new Boolean(false) from isTraversable will not allow a directory to be opened; instead, double-clicking on a directory will select the directory instead of opening it.

It should be pointed out that isTraversable returns a Boolean object and not a boolean value because returning null from FileView methods causes the associated file chooser to get the corresponding value from the default file view.8

File Type and Description

public abstract String getDescription(File)
public abstract String getTypeDescription(File)

The getDescription and getTypeDescription methods return a description of a specific file and a description of a file type, respectively. For example, for a file named FileChooserExample.java, the getDescription method might return "an example of using file choosers" and the getTypeDescription might return "a Java source code file."

As of Swing1.1 FCS, the getDescription and getTypeDescription methods are not used within Swing. The methods are meant for look and feels that wish to provide additional information about files in a file chooser.

The file chooser shown in Figure 16-7 is fitted with a custom extension of the FileView class that provides alternative icons for files and directories. Files ending in ".gif", ".bmp," and ".jpg" are represented by a different icon than the one used for other types of files.

Figure 16-07Figure 16-7 A Custom File View

The application that shows the file chooser shown in Figure 16-7 creates an instance of CustomFileView that is subsequently specified as the file chooser's file view.

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Custom File View Example");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setFileView(new CustomFileView());
    ...
  }
  ...
}

The CustomFileView class implements the getName, getDescription, and getTypeDescription to return null, which causes the values to be obtained from the file chooser's look and feel.

The CustomFileView method implements the getIcon and isTraversable methods. CustomFileView.getIcon() returns an icon that is appropriate for the type of file, and isTraversable method returns true except for a file—D:\file.txt—and a directory, D:\books.

class CustomFileView extends FileView {
  private Icon   fileIcon = new ImageIcon("file.gif"), 
           directoryIcon = new ImageIcon("folder.gif"),
           imageIcon = new ImageIcon("photo.jpg");

  public String getName(File f) { return null; }
  public String getDescription(File f) { return null; }
  public String getTypeDescription(File f) { return null; }

  public Icon getIcon(File f) {
    Icon icon = null;

    if(isImage(f))           icon = imageIcon;
    else if(f.isDirectory()) icon = directoryIcon;
    else           icon = fileIcon;

    return icon;
  }
  public Boolean isTraversable(File f) {
    Boolean b;

    if(f.getPath().equals("D:\\file.txt")) {
      b = new Boolean(false);
    }
    else if(f.getPath().equals("D:\\books")) {
      b = new Boolean(false);
    }
    return b == null ? new Boolean(true) : b;
  }
  private boolean isImage(File f) {
    String suffix = getSuffix(f);
    boolean isImage = false;

    if(suffix != null) {
      isImage = suffix.equals("gif") || 
            suffix.equals("bmp") ||
              suffix.equals("jpg");
    }
    return isImage;
  }
  private String getSuffix(File file) {
    String filestr = file.getPath(), suffix = null;
    int i = filestr.lastIndexOf('.');

    if(i > 0 && i < filestr.length()) {
      suffix = filestr.substring(i+1).toLowerCase();  
    }
    return suffix;
  }
}

The application shown in Figure 16-7 is listed in its entirety in Example 16-6.

Example 16-6 A Custom File View

import javax.swing.*;
import javax.swing.filechooser.FileView;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Custom File View Example");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setFileView(new CustomFileView());

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showSaveDialog(null);
        File file = chooser.getSelectedFile();
        String s = "CANCELED";

        if(state == JFileChooser.APPROVE_OPTION) 
          s = "File: " + file.getPath();

        JOptionPane.showMessageDialog(null, s);
      }
    });
  }
  public static void main(String args[]) {
    JFrame f = new Test();
    f.setBounds(300,300,350,100);
    f.setVisible(true);

    f.setDefaultCloseOperation(
                WindowConstants.DISPOSE_ON_CLOSE);

    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);  
      }
    });
  }
}
class CustomFileView extends FileView {
  private Icon fileIcon = new ImageIcon("file.gif"), 
         directoryIcon = new ImageIcon("folder.gif"),
         imageIcon = new ImageIcon("photo.jpg");

  public String getName(File f) { return null; }
  public String getDescription(File f) { return null; }
  public String getTypeDescription(File f) { return null; }

  public Icon getIcon(File f) {
    Icon icon = null;

    if(isImage(f))       icon = imageIcon;
    else if(f.isDirectory()) icon = directoryIcon;
    else           icon = fileIcon;

    return icon;
  }
  public Boolean isTraversable(File f) {
    Boolean b;

    if(f.getPath().equals("D:\\file.txt")) {
      b = new Boolean(false);
    }
    else if(f.getPath().equals("D:\\books")) {
      b = new Boolean(false);
    }
    return b == null ? new Boolean(true) : b;
  }
  private boolean isImage(File f) {
    String suffix = getSuffix(f);
    boolean isImage = false;

    if(suffix != null) {
      isImage = suffix.equals("gif") || 
           suffix.equals("bmp") ||
             suffix.equals("jpg");
    }
    return isImage;
  }
  private String getSuffix(File file) {
    String filestr = file.getPath(), suffix = null;
    int i = filestr.lastIndexOf('.');

    if(i > 0 && i < filestr.length()) {
      suffix = filestr.substring(i+1).toLowerCase();  
    }
    return suffix;
  }
}

Multiple Selection

Instances of JFileChooser allow multiple files to be selected; however, for Swing 1.1 FCS, although multiple files can be selected in a file chooser, the files selected cannot be accessed.

The file chooser shown in Figure 16-8 allows multiple selection.

Figure 16-8Figure 16-8 Selecting Multiple Files

The file chooser shown in Figure 16-8 has multiple selection enabled by a call to JFileChooser.setMultiSelectionEnabled(true). After the file chooser has been dismissed, the selected files are retrieved with JFileChooser.getSelectedFiles(), which under Swing 1.1 FCS always returns null.

The applet shown in Figure 16-8 is listed in its entirety in Example 16-7.

Example 16-7 Multiple Selection for File Chooser

import java.awt.*;

import java.awt.event.*;
import java.io.File;
import javax.swing.*;
import java.beans.*;

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Simple File Chooser Application");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    chooser.setMultiSelectionEnabled(true);

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        int state = chooser.showOpenDialog(null);
        File[] files = chooser.getSelectedFiles();
        String[] filenames = getFilenames(files);

        if(filenames != null &&
          state == JFileChooser.APPROVE_OPTION) {
          JOptionPane.showMessageDialog(null,filenames);
        }
        else if(state == JFileChooser.CANCEL_OPTION) {
          JOptionPane.showMessageDialog(
                      null, "Canceled");
        }
        else if(state == JFileChooser.ERROR_OPTION) {
          JOptionPane.showMessageDialog(
                      null, "Error!");
        }
      }
    });
  }
  private String[] getFilenames(File[] files) {
    String[] filenames = null;
    int numFiles = files.length;

    if(files.length > 0) {
       filenames = new String[numFiles];

      for(int i=0; i < numFiles; ++i) {
        filenames[i] = files[i].getPath();
        System.out.println(filenames[i]);
      }
    }
    return filenames;
  }
  public static void main(String args[]) {
    JFrame f = new Test();
    f.setBounds(300,300,350,100);
    f.setVisible(true);

    f.setDefaultCloseOperation(
      WindowConstants.DISPOSE_ON_CLOSE);
  
    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);  
      }
    });
  }
}

The JFileChooser class is summarized in Component Summary 16-1.

Component Summary 16-1 JFileChooser

Model(s)

——

UI Delegate(s)

javax.swing.plaf.basic.BasicFileChooserUI

Renderer(s)

——

Editor(s)

——

Events Fired

PropertyChangeEvents, ActionEvents

Replacement For

java.awt.FileDialog

Class Diagrams


Figure 16-9Figure 16-9 JFileChooser Class Diagram


JFileChooser extends JComponent and implements the Accessible interface. JFileChooser maintains private references to its accessory component, file filters, and file views. JFileChooser maintains private references to objects that represent JFileChooser properties, which are discussed in "JFileChooser Properties" on page 958.

JFileChooser also maintains public static integer values representing the three file chooser modes: DIRECTORIES_ONLY, FILES_ONLY, and FILES_AND_DIRECTORIES, in addition to dialog types and selection options. Additionally, JFileChooser maintains public static strings representing property names, open and save dialogs, etc. See "JFileChooser Class Summaries" on page 968 for more information concerning the public string constants defined by the JFileChooser class.

JFileChooser Properties

The properties maintained by the JFileChooser class are listed in Table 16-2.

Table 16-2 JFileChooser Properties

Property Name

Data Type

Property Type9

Access10

Default11

acceptAllFileFilter

FileFilter

S

G

L&F

accessory

JComponent

B

SG

null

approveButton-Mnemonic

int

B

SG

0

approveButton-Text

String

B

SG

——

approveButton-ToolTipText

String

B

SG

null

choosableFile-Filters

FileFilter[]

B

G

see discussion below

currentDirectory

File

B

CSG

——

description

String

S

G

——

dialogTitle

String

B

SG

L&F

dialogType

int

B

SG

OPEN_DIALOG

fileFilter

 

B

SG

L&F

fileHidingEnabled

boolean

B

SG

true

fileSelectionMode

int

B

SG

FILES_ONLY

fileSystemView

FileSystemView

B

CSG

null

fileView

FileView

B

SG

null

icon

Icon

S

G

L&F

multiSelection-Enabled

boolean

B

SG

false

name

String

S

G

——

selectedFile

File

B

SG

null

selectedFiles

File[]

B

SG

null

traversable

boolean

S

G

——

typeDescription

String

S

G

——


acceptAllFileFilter — Represents the default file filter that accepts all files. The property is maintained by the file chooser's UI delegate, making it look-and-feel dependent. It also is read-only and is accessible with the JFileChooser.getAcceptAllFilter method.

See "Filtering File Types" on page 936 for more information concerning the acceptAllFileFilter property and file filters in general.

accessory — An instance of JComponent that can be used for multiple purposes, the most common of which are previewers for different file types. See "Accessory Components" on page 930 for more information concerning file chooser accessory components.

approveButtonMnemonic — Represents the mnemonic associated with a file chooser's approve button. The mnemonic is set with the JFileChooser.setApproveButtonMnemonic method. See "Button Mnemonics" on page 415 for more information concerning button mnemonics in general.

approveButtonText — File choosers are equipped with two buttons, one for approving the selected file and another for canceling the file chooser dialog. The text associated with the approve button can be explicitly set.

Setting the approve button text sets the dialogType property to CUSTOM_DIALOG. Calling JFileChooser.showOpenDialog() or JFileChooser.showSaveDialog() sets the approve button text to a look-and-feel-specific string.

approveButtonToolTipText — A file chooser's approve button can have a tooltip associated with it. The default tooltip is look-and-feel dependent and can be overridden with the JFileChooser.setApproveButtonText method.

choosableFileFilters — A file chooser can have any number of choosable file filters associated with it. Choosable file filters can be added to and removed from a file chooser with the JFileChooser addChoosableFileFilter and removeChoosableFileFilter methods, respectively.

The set of choosable file filters always includes the "accept all" file filter. See the acceptAllFilter property for more information concerning the "accept all" file filter.

currentDirectory — An instance of java.io.File that represents the directory currently displayed in a file chooser. The currentDirectory property can be set at construction time or any time thereafter.

If the currentDirectory property is specified as a file instead of a directory, the current directory is set to the first traversable parent directory of the file specified.

dialogTitle — Is look-and-feel dependent and represents the title of the dialog in which a file chooser is displayed when the following JFileChooser methods are used: showOpenDialog(), showSaveDialog(), and showDialog().

The dialogTitle property has no effect if a file chooser is manually placed in a dialog. See Example 16-8 on page 967 for an example of manually placing a file chooser in a dialog.

dialogType — The dialogType property can be assigned one of the following JFileChooser constants:

JFileChooser.OPEN_DIALOG

JFileChooser.SAVE_DIALOG

JFileChooser.CUSTOM_DIALOG

The dialogType property sets a file chooser's approve button text if the property is set to either OPEN_DIALOG or CLOSE_DIALOG. See the dialogType property for more information concerning the constants listed above.

fileFilter — File filters for a file chooser can be set in one of two ways: with JFileChooser.addChoosableFileFilter() or with JFileChooser.setFileFilter(), both of which are passed an extension of the abstract swing.filechooser.FileFilter class.

JFileChooser.setFileFilter() replaces the current file filter(s), whereas addChoosableFileFilter adds a filter to the current list of file filters.

fileHidingEnabled — A boolean value that determines whether or not hidden files are displayed in JFileChooser.

fileSelectionMode — The fileSelectionMode property can be set to one of the following values:

JFileChooser.FILES_ONLY

JFileChooser.FILES_AND_DIRECTORIES

JFileChooser.DIRECTORIES_ONLY

The fileSelectionMode property determines whether files and/or directories are displayed in a file chooser.

fileSystemView — An instance of the swing.filechooser.FileSystemView class, which is summarized in Class Summary 15-7.

Class Summary 15-7 FileSystemView

Extends: java.lang.Object

Constructors

public FileSystemView()

The constructor is compiler generated.

Methods

public static FileSystemView getFileSystemView()
public File createFileObject(File, String)
public File createFileObject(String)
public abstract File createNewFolder(File) throws IOException
public File[] getFiles(File, boolean)
public File getHomeDirectory()
public File getParentDirectory(File)
public abstract File[] getRoots()
public abstract boolean isHiddenFile(File)
public abstract boolean isRoot(File)

FileSystemView provides platform-specific file information, such as root partitions and file type information, that is not available from the JDK1.1 java.io.File API.

The JFileChooser fileSystemView property will rarely be explicitly set by developers.

fileView — An object whose class is an extension of the abstract swing.filechooser.FileView class. File views provide information pertaining to the manner in which files are represented in a file chooser. By default, the information provided by a file view is obtained from a file chooser's look and feel; however, a file chooser's file view can be explicitly set.

See "FileView" on page 949 for more information concerning file views.

multiSelectionEnabled — File choosers support multiple selection, and the multiSelectionEnabled property controls whether a file chooser allows single or multiple selection. By default, file choosers allow single selection.

If a file chooser supports only single selection, the selected file is obtained by invocation of JFileChooser.getSelectedFile()—see the selectedFile property. If a file chooser supports multiple selection, the selected files are obtained by invocation of JFileChooser.getSelectedFiles()—see the selectedFiles property.

selectedFile — Represents the currently selected file in a file chooser. The selected file can be set either by user manipulation of a file chooser or programmatically with the JFileChooser.setSelectedFile method.

selectedFiles — If a file chooser has multiple selection enabled—see the multiSelectionEnabled property—the selected files are obtained by invocation of JFileChooser.getSelectedFiles().

The selected files in a file chooser can be set programmatically with the JFileChooser.setSelectedFiles method, which is passed an array of java.io.File instances.

description

name

icon

typeDescription — The properties listed above are actually maintained by a file chooser's file view. All of the properties listed above are read-only, and the values are obtained from the file chooser's file view.

JFileChooser Events

The JFileChooser class fires two types of events: action events and property change events. Action events are fired by file choosers whenever their Approve or Cancel buttons are activated.

Property change events are fired whenever a file chooser's bound properties are modified—see "JFileChooser Properties" on page 958 for a list of bound JFileChooser properties.

Action Events

By default, the dialogs displayed as a result of invoking showOpenDialog(), showSaveDialog(), or showDialog() are modal, and therefore references to the selected file(s) can be obtained with a line of code after the call to one of the methods listed above, as the code fragment below illustrates.

// code fragment

int state = chooser.showOpenDialog();         // shows modal dialog
file = chooser.getSelectedFile(); // invoked after dialog
                     // dialog is dismissed

In the code fragment listed above, the second line of code is not executed until the dialog is dismissed, and therefore the file returned from getSelectedFile() represents the file selected from the file chooser.

On the other hand, non-modal dialogs do not suspend execution of the thread that displays the dialog. As a result, a reference to selected file(s) for a file chooser displayed in a non-modal dialog cannot be obtained in the same fashion as illustrated in the code fragments above. For example, consider the following code fragment:

// code fragment

JDialog dialog = new JDialog(null, title, false);

// add chooser to dialog, set dialog title, etc.

dialog.setVisible(true);                        // show non-modal dialog
file = chooser.getSelectedFile(); // dialog has not
                     // been dismissed

In the code fragment listed above, the dialog is non-modal, which means the line of code that invokes JFileChooser.getSelectedFile() is executed before the dialog is dismissed. As a result, the file returned from getSelectedFile() in the code fragment above will return the last file selected from the file chooser or null if it is the first time the chooser has been displayed.

An alternative method for reacting to the dismissal of a file chooser dialog is to register an action listener with the file chooser. When the Approve or Cancel buttons in a file chooser are activated, the file chooser fires an action event. As a result, action listeners can be used to react to selections from—or cancellations of—a file chooser.

The file chooser shown in Figure 16-10 is contained in a non-modal dialog. The application that displays the dialog illustrates reacting to selections made from a file chooser.

Figure 16-10Figure 16-10 JFileChooser Action Events

The application contains a button whose activation results in the display of the dialog shown in Figure 16-10. The application creates a file chooser and a button. The button is added to the applet's content pane, and an action listener is added to the button that creates a non-modal dialog, adds the file chooser to the dialog, and displays the dialog.

The dialog's title is obtained by first invoking JFileChooser.getDialogTitle(). If the dialog title has been explicitly set, the call to JFileChooser.getDialogTitle() will return the title; otherwise, the method will return null. If the dialog title has not been explicitly set, the title is obtained from the chooser's UI delegate.

The dialog is created with a null frame, which results in the dialog being centered on the screen when it is displayed. The third argument to the JDialog constructor determines the modality of the dialog; in this case, a false value results in a non-modal dialog.

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JDialog dialog;
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Simple File Chooser Application");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String title = chooser.getDialogTitle();

        if(title == null)
          chooser.getUI().getDialogTitle(chooser);

            dialog = new JDialog((Frame)null, title, false);
        
            Container dialogContentPane = 
                dialog.getContentPane();

            dialogContentPane.setLayout(new BorderLayout());
            dialogContentPane.add(chooser, 
                BorderLayout.CENTER);
 
        dialog.setTitle("Non-Modal File Chooser");

            dialog.pack();
            dialog.setLocationRelativeTo(Test.this);
 
         dialog.setVisible(true);      
      }
    });
    ...

An action listener is also added to the chooser itself. The listener uses the action command associated with the action event to determine if a selection was made from the file chooser or if the dialog containing the chooser was canceled. If a selection was made from the file chooser, the selected file is obtained by invocation of JFileChooser.getSelectedFile. Subsequently, a message dialog is displayed, and the visibility of the dialog containing the chooser dialog is set to false.

    ...
    chooser.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String state = (String)e.getActionCommand();
        File file = chooser.getSelectedFile();

        if(file != null &&
           state.equals(JFileChooser.APPROVE_SELECTION)) {
          JOptionPane.showMessageDialog(
                      null, file.getPath());
        }
        else if(
          state.equals(JFileChooser.CANCEL_SELECTION)) {
          JOptionPane.showMessageDialog(
                      null, "Canceled");
        }
        // JFileChooser action listeners are notified
        // when either the approve button or
        // cancel button is activated
        dialog.setVisible(false);
      }
    });
  }

The applet shown in Figure 16-10 is listed in its entirety in Example 16-8.

Example 16-8 JFileChooser Action Events

import java.awt.*;

import java.awt.event.*;
import java.io.File;
import javax.swing.*;

public class Test extends JFrame {
  JFileChooser chooser = new JFileChooser();
  JDialog dialog;
  JButton button = new JButton("show file chooser ...");

  public Test() {
    super("Simple File Chooser Application");
    Container contentPane = getContentPane();

    contentPane.setLayout(new FlowLayout());
    contentPane.add(button);    

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String title = chooser.getDialogTitle();

        if(title == null)
          chooser.getUI().getDialogTitle(chooser);

            dialog = new JDialog(null, title, false);
        
            Container dialogContentPane = 
                dialog.getContentPane();

            dialogContentPane.setLayout(new BorderLayout());
              dialogContentPane.add(chooser, 
                BorderLayout.CENTER);
 
        dialog.setTitle("Non-Modal File Chooser");

            dialog.pack();
            dialog.setLocationRelativeTo(Test.this);
 
            dialog.setVisible(true);      
      }
    });
    chooser.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String state = (String)e.getActionCommand();
        File file = chooser.getSelectedFile();

        if(file != null &&
          state.equals(JFileChooser.APPROVE_SELECTION)) {
          JOptionPane.showMessageDialog(
                      null, file.getPath());
        }
        else if(
          state.equals(JFileChooser.CANCEL_SELECTION)) {
          JOptionPane.showMessageDialog(
                      null, "Canceled");
        }
        // JFileChooser action listeners are notified
        // when either the approve button or
        // cancel button is activated
        dialog.setVisible(false);
      }
    });
  }
  public static void main(String args[]) {
    JFrame f = new Test();
    f.setBounds(300,300,350,100);
    f.setVisible(true);

    f.setDefaultCloseOperation(
      WindowConstants.DISPOSE_ON_CLOSE);
  
    f.addWindowListener(new WindowAdapter() {
      public void windowClosed(WindowEvent e) {
        System.exit(0);  
      }
    });
  }
}

JFileChooser Class Summaries

The public and protected variables and methods for JFileChooser are listed in Class Summary 15-8.

Class Summary 15-8 JFileChooser

Extends: JComponent

Implements: javax.accessibility.Accessible

Constants

public static final String ACCESSORY_CHANGED_PROPERTY
public static final String
      APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY

public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY
public static final String
      APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY

public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY
public static final String DIALOG_TYPE_CHANGED_PROPERTY
public static final String DIRECTORY_CHANGED_PROPERTY
public static final String FILE_FILTER_CHANGED_PROPERTY
public static final String FILE_HIDING_CHANGED_PROPERTY
public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY
public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY
public static final String FILE_VIEW_CHANGED_PROPERTY
public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY
public static final String SELECTED_FILE_CHANGED_PROPERTY

The constants listed above identify the properties maintained by the JFileChooser class, as in the code fragment listed below:

// code fragment

chooser.addPropertyChangeListener(new PropertyChangeListener() {
  public void propertyChange(PropertyChangeEvent e) {
    if(e.getPropertyName().equals(
              JFileChooser.ACCESSORY_CHANGED_PROPERTY)
    // react to accessory change
  }
});

Dialog Types

public static final int CUSTOM_DIALOG
public static final int OPEN_DIALOG
public static final int SAVE_DIALOG

The constants listed above are mostly used internally by JFileChooser but are also passed to the JFileChooser.setDialogType method. If file choosers are displayed with the JFileChooser methods showOpenDialog(), showSaveDialog(), or showDialog(), dialog type is automatically set to OPEN_DIALOG, SAVE_DIALOG, and CUSTOM_DIALOG, respectively. If a file chooser is displayed in a dialog without the use of JFileChooser.show... methods, the dialog type will default to OPEN_DIALOG.

Because dialog type corresponds to a file chooser's approve button text, it may be desirable to explicitly set dialog type with either OPEN_DIALOG or SAVE_DIALOG when file choosers are displayed by means other than the JFileChooser.show... methods. (Setting dialog type to CUSTOM_DIALOG does not affect a file chooser's approve button text.)

Modes

public static final int DIRECTORIES_ONLY
public static final int FILES_AND_DIRECTORIES
public static final int FILES_ONLY

The constants listed above represent the three modes supported by the JFileChooser class. The constants are passed to the JFileChooser.setFileSelectionMode method.

Options / Approve-Cancel

public static final int APPROVE_OPTION
public static final int CANCEL_OPTION
public static final int ERROR_OPTION
public static final String APPROVE_SELECTION
public static final String CANCEL_SELECTION

The first group of constants listed above are returned from JFileChooser.showDialog(), JFileChooser.showOpenDialog(), and JFileChooser.showSaveDialog(). If the file chooser's approve button is activated, the methods return APPROVE_OPTION, whereas CANCEL_OPTION is returned in response to an activation of the Cancel button. The ERROR_OPTION is reserved for use when an error occurs while a file chooser dialog is displayed. As of Swing1.1, JFileChooser.ERROR_OPTION is not used within Swing.

The second group of constants are used as action command strings for action events fired by file choosers as a result of either Approve or Cancel button activation.

Constructors

public JFileChooser()
public JFileChooser(FileSystemView)
public JFileChooser(File currentDirectory)
public JFileChooser(File currentDirectory, FileSystemView)
public JFileChooser(String currentDirectoryPath)
public JFileChooser(String currentDirectoryPath, FileSystemView)
protected void setup(FileSystemView)

The no-argument constructor creates a file chooser with the user's home directory as the initially displayed directory.

Files passed to JFileChooser constructors determine the initially displayed directory. If the file is not a directory, the initially displayed directory is set to the file's first ancestor directory that is traversable.

FileSystemView objects passed to JFileChooser constructors are used to obtain file information. See "JFileChooser Properties" on page 958 for a discussion of the JFileChooser fileSystemView property.

The protected setup method sets the file system view, updates the UI delegate, and updates the file chooser's UI delegate.

Methods

Accessory Component

public JComponent getAccessory()
public void setAccessory(JComponent)

The methods listed above are accessors for a file chooser's accessory component. The setAccessory method fires a property change event if the new accessory component is different from the old.

Approve Button

public int getApproveButtonMnemonic()
public String getApproveButtonText()
public String getApproveButtonToolTipText()

public void setApproveButtonMnemonic(char)
public void setApproveButtonMnemonic(int)
public void setApproveButtonText(String)
public void setApproveButtonToolTipText(String)

A file chooser's approve button can be customized in three ways: the button's text, its tooltip, and its mnemonic. The methods listed above are accessors for the button's properties.

All of the setter methods listed above fire property change events if the value they are passed is different from the file chooser's current value. The approve button mnemonic can be set with either an integer or a character.

The setApproveButtonToolTipText method sets the dialog type to JFileChooser.CUSTOM_DIALOG.

Boolean Properties

public void setFileHidingEnabled(boolean)
public boolean isFileHidingEnabled()

public boolean isDirectorySelectionEnabled()
public boolean isFileSelectionEnabled()

File hiding corresponds to whether hidden files (such as files that begin with '.' under UNIX) are displayed in a file chooser.

The last two methods listed above can be used to determine whether directory or file selection is enabled.

Dialogs

public int showDialog(Component parent, String approveButtonText)
public int showOpenDialog(Component parent)
public int showSaveDialog(Component parent)

public String getDialogTitle()
public int getDialogType()

public void setDialogTitle(String)
public void setDialogType(int)

The first group of methods listed above display a modal dialog containing a file chooser on whose behalf the method is invoked. The integer value returned by the methods is one of the following constants:

JFileChooser.CANCEL_OPTION

JFileChooser.APPROVE_OPTION

Dialog title and type are accessed by the last four methods listed above. The setDialog... methods take effect only if a file chooser is displayed by one of the JFileChooser.show... methods.

Files and Directories

public void changeToParentDirectory()
public void rescanCurrentDirectory()

public File getCurrentDirectory()
public void setCurrentDirectory(File)

The changeToParentDirectory method delegates to the file chooser's file system view, and the rescanCurrentDirectory delegates to the UI delegate.

The last two methods listed above are accessors for a file chooser's current directory. If a file is passed to setCurrentDirectory that is not a directory, the current directory is set to the first traversable parent directory of the specified file.

File Filters

public FileFilter getAcceptAllFileFilter()
public FileFilter getFileFilter()
public void setFileFilter(FileFilter)

public void addChoosableFileFilter(FileFilter)
public boolean removeChoosableFileFilter(FileFilter)

public FileFilter[] getChoosableFileFilters()
public void resetChoosableFileFilters()

By default, file choosers are equipped with a single "accept all" filter that accepts all files. The "accept all" filter can be accessed by the getAcceptAllFileFilter method. The getFileFilter and setFileFilter methods can be used to get and set the currently selected filter.

File choosers can have more than one filter, although only one can be active at any given time. Filters can be added to and removed from a file chooser with the addChoosableFileFilter and removeChoosableFileFilter methods.

The getChoosableFileFilters method returns all of the filters associated with a file chooser, and the resetChoosableFileFilters method resets the list of filters to the "accept all" filter.

FileViews

public FileView getFileView()
public void setFileView(FileView)

public boolean accept(File)
public String getDescription(File)
public Icon getIcon(File)
public String getName(File)
public String getTypeDescription(File)
public boolean isTraversable(File)

File choosers have a file view object that extends the abstract swing.filechooser.FileView class, and JFileChooser provides accessors for the file view.

The second group of methods delegate directly to a file chooser's file view.

FileSystemView

public FileSystemView getFileSystemView()
public void setFileSystemView(FileSystemView)

File choosers delegate operating-system-dependent functionality to an object that extends the abstract swing.filechooser.FileSystemView class. The methods listed above are accessors for a file chooser's file system view.

Listeners

public void addActionListener(ActionListener)
public void removeActionListener(ActionListener)

protected void fireActionPerformed(String)

File choosers fire action events when their buttons are activated. As a result, JFileChooser provides methods for adding and removing action listeners. The protected fireActionPerformed method fires an action event to all registered action listeners.

Programmatic Manipulation

public void approveSelection()
public void cancelSelection()
public void ensureFileIsVisible(File)

File choosers can be manipulated programmatically by the methods listed above. Invoking approveSelection() mimics the activation of a file chooser's approve button, and the cancelSelection method mimics the activation of a file chooser's cancel button. There is no way to distinguish whether a selection or cancellation was initiated programmatically or by a user gesture.

The ensureFileIsVisible method scrolls the specified file into view.

NOTE

ensureFileIsVisible() does not work for all look and feels as of Swing 1.1 FCS.

File Selection Mode

public void setFileSelectionMode(int)
public int getFileSelectionMode()

File choosers support three selection modes, as defined by the integer constants listed below:

DIRECTORIES_ONLY

FILES_AND_DIRECTORIES

FILES_ONLY

The constants are passed to the setFileSelectionMode method. The current selection mode can be obtained by getFileSelectionMode().

Multiple Selection and Selected Files

public void setMultiSelectionEnabled(boolean)
public boolean isMultiSelectionEnabled()

public File getSelectedFile()
public void setSelectedFile(File)

public File[] getSelectedFiles()
public void setSelectedFiles(File[])

File choosers support both single and multiple selection. The first two methods listed above are accessors for the boolean multiSelectionEnabled property.

The last four methods listed above are accessors for the selected file(s); the first two methods are used for file choosers with single selection, and the last two methods are used for file choosers with multiple selection.

NOTE

Multiple selection is not fully supported in Swing 1.1 FCS.

Accessibility / Pluggable Look and Feel

public AccessibleContext getAccessibleContext()
public FileChooserUI getUI()
public String getUIClassID()
public void updateUI()

The methods listed above can be found in most extensions of JComponent. Swing lightweight components can return the class name of their UI delegate and an accessibility context that contains accessibility information for the component. The updateUI method is invoked when the component is fitted with a UI delegate.

AWT Compatibility

The main difference between the AWT's FileDialog and Swing's JFileChooser—other than the fact that Swing file choosers are much more capable—is the fact that the AWT's file dialogs deal in strings, whereas JFileChooser deals with files.

Table 16-3 lists the public methods implemented by the java.awt.FileDialog class and their JFileChooser equivalents.

Table 16-3 java.awt.FileDialog Methods & JFileChooser Equivalents

java.awt.FileDialog Methods

JFileChooser Equivalent

String getDirectory()

File getCurrentDirectory()

String getFile()

File getSelectedFile()

FilenameFilter getFilenameFilter()

FileFilter getFileFilter()

int getMode()

int getFileSelectionMode()

void setDirectory(String)

void setCurrentDirectory(File)

void setFile(String)

void setSelectedFile(File)

void setFilenameFilter(FilenameFilter)

void setFileFilter(FileFilter)

void setMode(int)

void setFileSelectionMode(int)


  • + Share This
  • 🔖 Save To Your Account

Discussions

comments powered by Disqus