I l@ve RuBoard |
![]() ![]() |
12.1 The JFileChooser ClassSince it plays such an integral role in just about every commercial application, let's look at the file chooser first. The JFileChooser class bundles a directory pane and typical selection buttons into a handy interface. Figure 12-2 shows the dialog window you get when you select the Save option of a simple application. As you might expect, other L&Fs can also be applied to this chooser. Figure 12-2. The JFileChooser save dialog (Metal L&F)![]() Figure 12-3 shows sample file choosers for open and save dialogs in the Windows, Motif, and Mac OS X L&Fs. Figure 12-3. JFileChooser in the Windows, Motif, and Mac L&Fs![]() The application itself reports only which file (or files, if you use the Open option) you chose to open or save. Our application has a Pick Directory button that restricts the chooser to directories. The event handlers for each button do most of the interesting work. In each case, we create a new JFileChooser object, make any changes to the default properties that we need for the particular action, and then show the dialog. As you will see from the constants discussed later, the int returned from the showDialog( ) method indicates whether the user accepted a file selection or canceled the dialog. If we have a successful selection, our example application puts the name of the file into a display label. Here's the code that generated the application. For this quick test, we create each file chooser dialog as we need it. You do not have to do this. You can save a reference to these dialogs and reuse them, just as you would other pop ups. // SimpleFileChooser.java // A simple file chooser to see what it takes to make one of these work // import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class SimpleFileChooser extends JFrame { public SimpleFileChooser( ) { super("File Chooser Test Frame"); setSize(350, 200); setDefaultCloseOperation(EXIT_ON_CLOSE); Container c = getContentPane( ); c.setLayout(new FlowLayout( )); JButton openButton = new JButton("Open"); JButton saveButton = new JButton("Save"); JButton dirButton = new JButton("Pick Dir"); final JLabel statusbar = new JLabel("Output of your selection will go here"); // Create a file chooser that opens up as an Open dialog. openButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent ae) { JFileChooser chooser = new JFileChooser( ); chooser.setMultiSelectionEnabled(true); int option = chooser.showOpenDialog(SimpleFileChooser.this); if (option == JFileChooser.APPROVE_OPTION) { File[] sf = chooser.getSelectedFiles( ); String filelist = "nothing"; if (sf.length > 0) filelist = sf[0].getName( ); for (int i = 1; i < sf.length; i++) { filelist += ", " + sf[i].getName( ); } statusbar.setText("You chose " + filelist); } else { statusbar.setText("You canceled."); } } }); // Create a file chooser that opens up as a Save dialog. saveButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent ae) { JFileChooser chooser = new JFileChooser( ); int option = chooser.showSaveDialog(SimpleFileChooser.this); if (option == JFileChooser.APPROVE_OPTION) { statusbar.setText("You saved " + ((chooser.getSelectedFile( )!=null)? chooser.getSelectedFile( ).getName( ):"nothing")); } else { statusbar.setText("You canceled."); } } }); // Create a file chooser that allows you to pick a directory // rather than a file. dirButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent ae) { JFileChooser chooser = new JFileChooser( ); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int option = chooser.showOpenDialog(SimpleFileChooser.this); if (option == JFileChooser.APPROVE_OPTION) { statusbar.setText("You opened " + ((chooser.getSelectedFile( )!=null)? chooser.getSelectedFile( ).getName( ):"nothing")); } else { statusbar.setText("You canceled."); } } }); c.add(openButton); c.add(saveButton); c.add(dirButton); c.add(statusbar); } public static void main(String args[]) { SimpleFileChooser sfc = new SimpleFileChooser( ); sfc.setVisible(true); } } 12.1.1 PropertiesThe JFileChooser class uses the properties shown in Table 12-1 for configuring most of the dialog's functionality.
The acceptAllFileFilter property provides access to the most common filter which, not surprisingly, accepts all files. You can set a more restrictive filter through the fileFilter property, or get a list of all the filters this dialog knows about with the choosableFileFilters property. The filters can also be affected by the fileHidingEnabled property, which, if true, does not display hidden files (such as files starting with "." on Unix systems). You can determine whether the dialog looks for files, directories, or both during the selection using the directorySelectionEnabled and fileSelectionEnabled convenience properties. The fileSelectionMode property is the real determining factor. You can use this property to select files, directories, or both with some of the constants presented later. Regardless of whether directories are selectable, double-clicking a directory opens that directory and makes it the new currentDirectory for the chooser. The number of files that can be selected (one or many) is determined by the multiSelectionEnabled property, which was fully implemented in the 1.4 release. (It was not implemented at all in 1.2. In 1.3, it can select multiple files, but the text field indicating which files are currently selected is not updated after the first file.) The selectedFile property contains the lead selection while the selectedFiles property holds several filenames, if multiple selections are allowed. The remaining properties dictate the visual appearance of the dialog. You can create save, open, and custom dialogs with the dialogType property and some of the constants discussed later. The icons and descriptions used for files and folders are managed with the fileView and fileSystemView properties. (The data types supporting these properties are discussed in more detail in the next section.) You can customize the text in the dialog by setting the dialogTitle property for the pop up's title, the approveButtonText property for the OK button, and the approveButtonToolTipText property for the button's tooltip text. The approveButtonMnemonic property is a virtual key value (one of the VK_ constants from KeyEvent) representing the letter you want underscored in the Approve button. Note that in setting this property, you can alternatively pass a char value to the set method. 12.1.2 File Chooser AccessoriesThe accessory property provides developers with an interesting hook into the dialog. You can create a custom component and attach it to the dialog. A typical example of such an accessory is an image viewer that shows you a thumbnail of any image file you have selected in the file selection window. Figure 12-4 shows a similar component that allows you to play music (.au, .wav, .aiff) files. Figure 12-4. A file chooser with an audio accessory that can play a selected .au file![]() Here's the code for the accessory. To react to the user selecting a new file, your accessory needs to implement the PropertyChangeListener interface. (We attach it as a listener in the main application following this code.) Notice how we check the property change being reported in the propertyChange( ) method, so that we react only to new file selections. If it is a file selection event, we grab the new filename from the PropertyChangeEvent object. The propertyChange( ) method is the heart of the program. You should use this method to update your accessory as the user moves around the filesystem. We also use the setCurrentClip( ) method to keep the accessory's GUI in sync with the selected file. This keeps the Play and Stop buttons inactive for nonaudio files so that users don't try to play a text file. // AudioAccessory.java // A simple accessory for JFileChooser that lets you play music clips // import javax.swing.*; import java.awt.*; import java.net.*; import java.beans.*; import java.io.*; import java.applet.*; import java.awt.event.*; public class AudioAccessory extends JPanel implements PropertyChangeListener, ActionListener { AudioClip currentClip; String currentName=""; JLabel fileLabel; JButton playButton, stopButton; public AudioAccessory( ) { // Set up the accessory. The file chooser will give us a reasonable size. setLayout(new BorderLayout( )); add(fileLabel = new JLabel("Clip Name"), BorderLayout.NORTH); JPanel p = new JPanel( ); playButton = new JButton("Play"); stopButton = new JButton("Stop"); playButton.setEnabled(false); stopButton.setEnabled(false); p.add(playButton); p.add(stopButton); add(p, BorderLayout.CENTER); playButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent e) { if (currentClip != null) { currentClip.stop( ); currentClip.play( ); } } }); stopButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent e) { if (currentClip != null) { currentClip.stop( ); } } }); } public void propertyChange(PropertyChangeEvent e) { String pname = e.getPropertyName( ); if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(pname)) { // The user selected a file in the chooser. File f = (File)e.getNewValue( ); // Be reasonably sure it's an audio file. if ((f != null) && (f.getName( ).toLowerCase( ).endsWith(".au") || f.getName( ).toLowerCase( ).endsWith(".wav") || f.getName( ).toLowerCase( ).endsWith(".aif") || f.getName( ).toLowerCase( ).endsWith(".aiff")) ) { setCurrentClip(f); } else { setCurrentClip(null); } } } public void setCurrentClip(File f) { if (currentClip != null) { currentClip.stop( ); } // Make sure we have a real file; otherwise, disable the buttons. if ((f == null) || (f.getName( ) == null)) { fileLabel.setText("no audio selected"); playButton.setEnabled(false); stopButton.setEnabled(false); return; } // It seems that the audio file is real, so load it and enable the buttons. String name = f.getName( ); if (name.equals(currentName)) { // Same clip they just loaded; make sure the player is enabled fileLabel.setText(name); playButton.setEnabled(true); stopButton.setEnabled(true); return; } currentName = name; try { URL u = new URL("file:///" + f.getAbsolutePath( )); currentClip = Applet.newAudioClip(u); } catch (Exception e) { e.printStackTrace( ); currentClip = null; fileLabel.setText("Error loading clip."); } fileLabel.setText(name); playButton.setEnabled(true); stopButton.setEnabled(true); } public void actionPerformed(ActionEvent ae) { // Be a little cavalier here. We're assuming the dialog was just // approved or canceled, so we should stop any playing clip. if (currentClip != null) { currentClip.stop( ); } } } Here's the application code that inserts the accessory into the chooser. The only real change we make is to the Open button's actionPerformed( ) method. Before we make the chooser visible, we use setAccessory( ) to get our audio accessory in place. We then attach the accessory as a property change listener to the chooser. This step ensures that the accessory is notified as the user selects new files. // AccessoryFileChooser.java // import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class AccessoryFileChooser extends JFrame { JFileChooser chooser = null; JLabel statusbar; public AccessoryFileChooser( ) { super("Accessory Test Frame"); setSize(350, 200); setDefaultCloseOperation(EXIT_ON_CLOSE); Container c = getContentPane( ); c.setLayout(new FlowLayout( )); JButton accButton = new JButton("Accessory"); statusbar = new JLabel("Output of your selection will go here"); chooser = new JFileChooser( ); AudioAccessory aa = new AudioAccessory( ); chooser.setAccessory(aa); chooser.addPropertyChangeListener(aa); // To receive selection changes chooser.addActionListener(aa); // To receive Approve/Cancel button events accButton.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent ae) { int option = chooser.showOpenDialog(AccessoryFileChooser.this); if (option == JFileChooser.APPROVE_OPTION) { statusbar.setText("You chose " + ((chooser.getSelectedFile( )!=null)? chooser.getSelectedFile( ).getName( ):"nothing")); } else { statusbar.setText("You canceled."); } } }); c.add(accButton); c.add(statusbar); } public static void main(String args[]) { AccessoryFileChooser afc = new AccessoryFileChooser( ); afc.setVisible(true); } } 12.1.3 EventsIn addition to the property change events generated by most other Swing components, the JFileChooser also generates action events when the user clicks on the OK or Cancel buttons. The event is fired after the dialog is hidden.
12.1.4 ConstantsThe JFileChooser class has several constants. These constants can be broken into two categories:
The constants in Table 12-3 provide values for many of the properties in the JFile-Chooser class.
12.1.5 Constructors
12.1.6 FileFilter MethodsThe choosableFileFilters property does not have a proper "set" method, but you can modify the set of available filters using these methods:
12.1.7 File and Directory MethodsThe file methods check files to find the appropriate names, descriptions, and icons to display in the chooser according to the active FileView and FileFilter objects. If you open a JFileChooser and switch to the detail view of the files, you'll see many of these methods in action.
12.1.8 Dialog Methods
![]() |
I l@ve RuBoard |
![]() ![]() |