文档

Java™教程
隐藏目录
使用文件选择器
路径: 使用Swing创建GUI
课程: 使用Swing组件
章节: 如何使用各种组件

如何使用文件选择器

文件选择器提供了一个用于浏览文件系统的GUI,然后从列表中选择文件或目录,或者输入文件或目录的名称。要显示文件选择器,通常使用JFileChooser API来显示包含文件选择器的模态对话框。另一种呈现文件选择器的方法是将JFileChooser实例添加到容器中。


注意: 

如果您打算将程序作为沙盒Java Web Start应用程序分发,那么您应该使用JNLP API提供的文件服务,而不是使用JFileChooser API。这些服务-FileOpenServiceFileSaveService不仅支持在受限环境中选择文件,还负责实际打开和保存文件。使用这些服务的示例在JWSFileChooserDemo中。有关使用JNLP API的文档可以在Java Web Start教程中找到。


点击“启动”按钮,使用Java™ Web Start运行JWSFileChooserDemo(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引

启动JWSFileChooserDemo应用程序

在使用JWSFileChooserDemo示例时,请小心不要丢失所需的文件。每当单击保存按钮并选择一个现有文件时,此演示会弹出一个“文件已存在”对话框,要求替换该文件。接受请求将覆盖该文件。

本节的其余部分讨论了如何使用JFileChooser API。 JFileChooser对象仅呈现用于选择文件的GUI。您的程序负责对所选择的文件执行某些操作,例如打开或保存文件。有关如何读取和写入文件的信息,请参阅基本I/O

JFileChooser API使打开和保存对话框变得容易。外观和感觉的类型决定了这些标准对话框的外观和差异。在Java外观和感觉中,保存对话框看起来与打开对话框相同,只是对话框窗口上的标题和批准操作的按钮上的文本不同。这是Java外观和感觉中标准打开对话框的图片:

一个展示了Java外观中标准打开对话框的图片

这是一个名为FileChooserDemo的应用程序的图片,它弹出了一个打开对话框和一个保存对话框。

一个弹出打开或保存对话框的程序

试一试: 
  1. 编译并运行示例,请参考示例索引
  2. 点击“打开文件”按钮。在文件选择器中导航,选择一个文件,然后点击对话框的“打开”按钮。
  3. 使用“保存文件”按钮弹出一个保存对话框。尝试使用文件选择器上的所有控件。
  4. 在源文件FileChooserDemo.java中,将文件选择模式更改为仅目录模式。(搜索DIRECTORIES_ONLY并取消包含它的行的注释。)然后重新编译并运行示例。您只能看到并选择目录,而不是普通文件。

弹出标准打开对话框只需要两行代码:

//创建文件选择器
final JFileChooser fc = new JFileChooser();
...
//响应按钮点击:
int returnVal = fc.showOpenDialog(aComponent);

showOpenDialog方法的参数指定了对话框的父组件。父组件影响对话框的位置和依赖的窗口。例如,Java外观会将对话框直接放在父组件上方。如果父组件在一个窗口中,则对话框依赖于该窗口。当窗口最小化时,对话框会消失;当窗口最大化时,对话框会重新出现。

默认情况下,未显示过的文件选择器会显示用户主目录中的所有文件。您可以使用JFileChooser的其他构造方法之一指定文件选择器的初始目录,或者可以使用setCurrentDirectory方法设置目录。

调用showOpenDialog出现在“打开文件”按钮的动作监听器的actionPerformed方法中:

public void actionPerformed(ActionEvent e) {
    //处理打开按钮的动作。
    if (e.getSource() == openButton) {
        int returnVal = fc.showOpenDialog(FileChooserDemo.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            //这是一个真实应用程序会打开文件的地方。
            log.append("正在打开:" + file.getName() + "。" + newline);
        } else {
            log.append("用户取消了打开命令。" + newline);
        }
   } ...
}

showXxxDialog方法返回一个整数,表示用户是否选择了文件。根据您如何使用文件选择器,通常只需要检查返回值是否为APPROVE_OPTION,然后不改变任何其他值。要获取选择的文件(或目录,如果您设置了文件选择器以允许选择目录),请在文件选择器上调用getSelectedFile方法。此方法返回一个File实例。

示例获取文件的名称并在日志消息中使用它。您可以在File对象上调用其他方法,例如getPathisDirectoryexists,以获取有关文件的信息。您还可以调用deleterename等其他方法以某种方式更改文件。当然,您可能还想通过使用Java平台提供的读取器或写入器类之一来打开或保存文件。有关使用读取器和写入器将数据读取和写入文件系统的信息,请参阅基本I/O

示例程序使用相同的JFileChooser类实例来显示标准的保存对话框。这次程序调用showSaveDialog

int returnVal = fc.showSaveDialog(FileChooserDemo.this);

通过使用相同的文件选择器实例来显示其打开和保存对话框,程序可以获得以下好处:

最后,示例程序中有一些被注释的代码行,可以让您更改文件选择模式。例如,下面的代码行使文件选择器只能选择目录而不是文件:

fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

另一个可能的选择模式是FILES_AND_DIRECTORIES。默认值是FILES_ONLY。下图显示了文件选择模式设置为DIRECTORIES_ONLY的打开对话框。请注意,至少在Java外观中,只有目录可见-而不是文件。

在DIRECTORIES_ONLY模式下的文件选择器

如果您想为除打开或保存之外的其他任务创建文件选择器,或者如果您想自定义文件选择器,请继续阅读。我们将讨论以下主题:

另一个示例:FileChooserDemo2

让我们来看一个FileChooserDemo2的示例,这是之前的演示程序的修改版本,它使用了更多的JFileChooser API。这个示例使用了一个已经定制化的文件选择器。与原始示例一样,用户通过点击按钮来调用文件选择器。下面是文件选择器的图片:

一个带有各种自定义功能的文件选择器

如图所示,这个文件选择器已经针对特定任务(附件)进行了定制,提供了用户可选择的文件过滤器(仅限图像),对图像文件使用了特殊的文件视图,并且还有一个附件组件,用于显示当前选中图像文件的缩略图。

本节的其余部分将向您展示创建和自定义这个文件选择器的代码。请参阅示例索引,以获取该示例所需的所有文件的链接。

将文件选择器用于自定义任务

正如您所看到的,JFileChooser类提供了showOpenDialog方法来显示打开对话框,以及showSaveDialog方法来显示保存对话框。

该类还有另一个方法showDialog,用于在对话框中显示文件选择器以执行自定义任务。在Java外观中,该对话框与其他文件选择器对话框之间的唯一区别是对话框窗口的标题和批准按钮的标签。下面是FileChooserDemo2中调用文件选择器对话框的代码:

JFileChooser fc = new JFileChooser();
int returnVal = fc.showDialog(FileChooserDemo2.this, "附件");

showDialog方法的第一个参数是对话框的父组件。第二个参数是一个String对象,用于提供对话框窗口的标题和批准按钮的标签。

同样,文件选择器不会对所选文件进行任何操作。程序需要负责实现为文件选择器创建的自定义任务。

过滤文件列表

默认情况下,文件选择器会显示它检测到的所有文件和目录,但会排除隐藏文件。程序可以为文件选择器应用一个或多个文件过滤器,以便只显示某些文件。文件选择器会对每个文件调用过滤器的accept方法,以确定是否应该显示该文件。文件过滤器根据文件类型、大小、所有权等标准接受或拒绝文件。过滤器会影响文件选择器显示的文件列表。用户可以输入任何文件的名称,即使它没有显示出来。

JFileChooser 支持三种不同类型的过滤。过滤器按照列在此处的顺序进行检查。例如,应用程序控制的过滤器只能看到内置过滤器接受的文件。

内置过滤器
通过文件选择器上的特定方法调用来设置过滤器。目前,唯一可用的内置过滤器是用于隐藏文件的过滤器,例如那些在UNIX系统上以句点(.)开头的文件。默认情况下,隐藏文件是不显示的。调用setFileHidingEnabled(false)来显示隐藏文件。
应用程序控制的过滤器
应用程序确定显示哪些文件。创建FileFilter的自定义子类,实例化它,并将实例作为参数传递给setFileFilter方法。安装的过滤器将显示在可供用户选择的过滤器列表中。文件选择器仅显示过滤器接受的文件。
用户可选择的过滤器
文件选择器GUI提供了用户可以选择的过滤器列表。当用户选择一个过滤器时,文件选择器只显示那些被该过滤器接受的文件。 FileChooserDemo2 将一个自定义文件过滤器添加到可供用户选择的过滤器列表中:
fc.addChoosableFileFilter(new ImageFilter());
默认情况下,可供用户选择的过滤器列表包括“接受所有”过滤器,这使用户可以看到所有非隐藏文件。此示例使用以下代码禁用“接受所有”过滤器:
fc.setAcceptAllFileFilterUsed(false);
我们的自定义文件过滤器在 ImageFilter.java 中实现,并且是 FileFilter 的子类。 ImageFilter 类实现了 getDescription 方法,返回“仅图像” - 一个要放在可供用户选择的过滤器列表中的字符串。 ImageFilter 还实现了 accept 方法,以便接受所有目录和具有 .png.jpg.jpeg.gif.tif.tiff 文件扩展名的文件。
public boolean accept(File f) {
    if (f.isDirectory()) {
        return true;
    }

    String extension = Utils.getExtension(f);
    if (extension != null) {
        if (extension.equals(Utils.tiff) ||
            extension.equals(Utils.tif) ||
            extension.equals(Utils.gif) ||
            extension.equals(Utils.jpeg) ||
            extension.equals(Utils.jpg) ||
            extension.equals(Utils.png)) {
                return true;
        } else {
            return false;
        }
    }

    return false;
}
通过接受所有目录,该过滤器允许用户在文件系统中导航。如果省略了加粗的行,用户将被限制在选择器初始化的目录中。

上面的代码示例使用了 getExtension 方法和 Utils.java 中的多个字符串常量,如下所示:

public class Utils {

    public final static String jpeg = "jpeg";
    public final static String jpg = "jpg";
    public final static String gif = "gif";
    public final static String tiff = "tiff";
    public final static String tif = "tif";
    public final static String png = "png";

    /*
     * 获取文件的扩展名。
     */  
    public static String getExtension(File f) {
        String ext = null;
        String s = f.getName();
        int i = s.lastIndexOf('.');

        if (i > 0 &&  i < s.length() - 1) {
            ext = s.substring(i+1).toLowerCase();
        }
        return ext;
    }
}

自定义文件视图

在Java外观中,选择器的列表显示每个文件的名称,并显示表示文件是真实文件还是目录的小图标。您可以通过创建FileView的自定义子类并将该类的实例作为setFileView方法的参数来自定义此文件视图。示例中使用了一个自定义类的实例,该类在ImageFileView.java中实现,作为文件选择器的文件视图。

fc.setFileView(new ImageFileView());

ImageFileView类为先前描述的图像过滤器接受的每种类型的图像显示不同的图标。

ImageFileView类覆盖了FileView中定义的五个抽象方法,如下所示。

String getTypeDescription(File f)
返回文件类型的描述。下面是ImageFileView的实现方法:
public String getTypeDescription(File f) {
    String extension = Utils.getExtension(f);
    String type = null;

    if (extension != null) {
        if (extension.equals(Utils.jpeg) ||
            extension.equals(Utils.jpg)) {
            type = "JPEG 图像";
        } else if (extension.equals(Utils.gif)){
            type = "GIF 图像";
        } else if (extension.equals(Utils.tiff) ||
                   extension.equals(Utils.tif)) {
            type = "TIFF 图像";
        } else if (extension.equals(Utils.png)){
            type = "PNG 图像";
        }
    }
    return type;
}
Icon getIcon(File f)
返回表示文件或其类型的图标。下面是ImageFileView的实现方法:
public Icon getIcon(File f) {
    String extension = Utils.getExtension(f);
    Icon icon = null;

    if (extension != null) {
        if (extension.equals(Utils.jpeg) ||
            extension.equals(Utils.jpg)) {
            icon = jpgIcon;
        } else if (extension.equals(Utils.gif)) {
            icon = gifIcon;
        } else if (extension.equals(Utils.tiff) ||
                   extension.equals(Utils.tif)) {
            icon = tiffIcon;
        } else if (extension.equals(Utils.png)) {
            icon = pngIcon;
        }
    }
    return icon;
}
String getName(File f)
返回文件的名称。大多数实现此方法的方式应该返回null,以表示外观应该自动确定。另一种常见的实现方式是返回f.getName()
String getDescription(File f)
返回文件的描述。意图是更具体地描述各个文件。该方法的常见实现返回null,以表示外观应该自动确定。
Boolean isTraversable(File f)
返回目录是否可遍历。大多数实现此方法的方式应该返回null,以表示外观应该自动确定。某些应用程序可能希望阻止用户进入某种类型的目录,因为它表示复合文档。对于非目录,isTraversable方法永远不应返回true

提供辅助组件

FileChooserDemo2中的自定义文件选择器具有一个辅助组件。如果当前选择的项是PNG、JPEG、TIFF或GIF图像,则辅助组件会显示图像的缩略图。否则,辅助组件为空。除了预览器外,辅助组件最常见的用途可能是一个带有更多控件的面板,例如在功能之间切换的复选框。

示例调用setAccessory方法来建立一个ImagePreview类的实例,该类实现在ImagePreview.java中,作为选择器的附件组件:

fc.setAccessory(new ImagePreview(fc));

任何从JComponent类继承的对象都可以作为附件组件。该组件应该有一个在文件选择器中显示良好的首选大小。

当用户在列表中选择项目时,文件选择器会触发属性更改事件。带有附件组件的程序必须注册接收这些事件,以便在选择更改时更新附件组件。在示例中,ImagePreview对象本身注册了这些事件。这样可以将所有与附件组件相关的代码放在一个类中。

以下是示例中propertyChange方法的实现,该方法在触发属性更改事件时调用:

//声明成员变量
File file = null;
...
public void propertyChange(PropertyChangeEvent e) {
    boolean update = false;
    String prop = e.getPropertyName();

    //如果目录发生更改,则不显示图像。
    if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
        file = null;
        update = true;

    //如果选择了文件,则找出哪个文件。
    } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
        file = (File) e.getNewValue();
        update = true;
    }

    //相应地更新预览。
    if (update) {
        thumbnail = null;
        if (isShowing()) {
            loadImage();
            repaint();
        }
    }
}

如果SELECTED_FILE_CHANGED_PROPERTY是更改的属性,则此方法从文件选择器中获取File对象。loadImagerepaint方法使用File对象来加载图像并重绘附件组件。

文件选择器API

使用文件选择器的API分为以下几个类别:

创建和显示文件选择器
方法或构造函数 目的
JFileChooser()
JFileChooser(File)
JFileChooser(String)
创建一个文件选择器实例。当存在FileString参数时,提供初始目录。
int showOpenDialog(Component)
int showSaveDialog(Component)
int showDialog(Component, String)
显示包含文件选择器的模态对话框。这些方法返回APPROVE_OPTION,如果用户批准了操作,返回CANCEL_OPTION,如果用户取消了操作。另一个可能的返回值是ERROR_OPTION,表示发生了意外错误。
选择文件和目录
方法 目的
void setSelectedFile(File)
File getSelectedFile()
设置或获取当前选定的文件或(如果启用了目录选择)目录。
void setSelectedFiles(File[])
File[] getSelectedFiles()
设置或获取当前选定的文件(如果文件选择器设置为允许多重选择)。
void setFileSelectionMode(int)
void getFileSelectionMode()
boolean isDirectorySelectionEnabled()
boolean isFileSelectionEnabled()
设置或获取文件选择模式。可接受的值为FILES_ONLY(默认值)、DIRECTORIES_ONLYFILES_AND_DIRECTORIES
根据当前选择模式解释可选择的目录或文件。
void setMultiSelectionEnabled(boolean)
boolean isMultiSelectionEnabled()
设置或解释是否可以一次选择多个文件。默认情况下,用户只能选择一个文件。
void setAcceptAllFileFilterUsed(boolean)
boolean isAcceptAllFileFilterUsed()
设置或获取是否在可选择的过滤器列表中使用AcceptAll文件过滤器作为可接受的选择;默认值为true
Dialog createDialog(Component) 给定一个父组件,创建并返回一个包含此文件选择器的新对话框,依赖于父组件的框架,并居中于父组件上方。
文件选择器列表的导航
方法 目的
void ensureFileIsVisible(File) 滚动文件选择器的列表,以使指定的文件可见。
void setCurrentDirectory(File)
File getCurrentDirectory()
设置或获取在文件选择器的列表中显示的目录。
void changeToParentDirectory() 将列表更改为显示当前目录的父目录。
void rescanCurrentDirectory() 检查文件系统并更新选择器的列表。
void setDragEnabled(boolean)
boolean getDragEnabled()
设置或获取确定是否启用自动拖动处理的属性。有关更多详细信息,请参见拖放和数据传输
自定义文件选择器
方法 目的
void setAccessory(javax.swing.JComponent)
JComponent getAccessory()
设置或获取文件选择器的附件组件。
void setFileFilter(FileFilter)
FileFilter getFileFilter()
设置或获取文件选择器的主要文件过滤器。
void setFileView(FileView)
FileView getFileView()
设置或获取选择器的文件视图。
FileFilter[] getChoosableFileFilters()
void addChoosableFileFilter(FileFilter)
boolean removeChoosableFileFilter(FileFilter)
void resetChoosableFileFilters()
FileFilter getAcceptAllFileFilter()
设置、获取或修改可供用户选择的文件过滤器列表。
void setFileHidingEnabled(boolean)
boolean isFileHidingEnabled()
设置或获取是否显示隐藏文件。
void setControlButtonsAreShown(boolean)
boolean getControlButtonsAreShown()
设置或获取属性,指示文件选择器中的“确定”和“取消”按钮是否显示。默认情况下,该属性为true。

使用文件选择器的示例

这个表格显示了使用文件选择器的示例,并指向这些示例所在的位置。

示例 描述位置 备注
FileChooserDemo 本节 显示打开对话框和保存对话框。
FileChooserDemo2 本节 使用具有自定义过滤器、自定义文件视图和附件组件的文件选择器。
JWSFileChooserDemo 本节 使用JNLP API来打开和保存文件。

上一页: 如何使用编辑窗格和文本窗格
下一页: 如何使用格式化文本字段