【问题标题】:Java FileFilter to select certain directoriesJava FileFilter 选择某些目录
【发布时间】:2014-03-10 13:57:05
【问题描述】:

我正在尝试创建一个 FileFilter,它只允许用户打开包含某个文件的目录。用例是这些目录是工作区,其中有一个名为 smart.workspace 的文件。

目前我的过滤器如下...

class SMARTWorkspaceFilter extends javax.swing.filechooser.FileFilter {

    String description = "SMART Workspace";
    String fileNameFilter = "smart.workspace";

    SMARTWorkspaceFilter() {

    }

    @Override
    public boolean accept(File file) {

        log.debug("Testing file: " + file.getName());

        if (file.isFile()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {

                log.debug("Directory: " + f.isDirectory());
                log.debug("Name: " + f.getName());

                if (f.isDirectory()) {
                    return true;
                }

                if (f.getName().equals(fileNameFilter)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public String getDescription() {
        return description;
    }
}

显然我的问题是,为了允许用户导航到工作区文件夹,我必须允许子目录。

对于文件选择器,我使用选项DIRECTORIES_ONLY

是否可以只允许用户根据目录内容选择目录?

例如目录 'workspace' 存在于 C://Folder1/Folder2/wokspace,我希望允许 FileChooser 在 C:// 'start' 并允许用户导航到 'workspace' 文件夹并接受它。 FileChooser 不应允许接受 Folder1 或 Folder2,但仍允许在 Folder1 和 Folder2 中导航。

【问题讨论】:

    标签: java jfilechooser filefilter


    【解决方案1】:

    我认为您不能让 FileFilter 区分“应该显示且可以访问的文件/目录”和“可以选择的文件/目录”。

    我想到的解决您的问题的方法是:让用户搜索/选择smart.workspace 文件,然后从那里导航到父文件夹。

    如果您需要对话框完全按照上述说明进行操作,则必须通过JFileChooser 详细参与。希望扩展该类可以让您有足够的访问权限来根据需要更改行为。

    【讨论】:

      【解决方案2】:

      您的问题是您的退货声明相互矛盾。您不需要第一个 if 语句,因为您默认返回 false(除非它是一个目录并且该目录包含特殊文件)。

      class SMARTWorkspaceFilter extends javax.swing.filechooser.FileFilter {
      
          String description = "SMART Workspace";
          String fileNameFilter = "smart.workspace";
      
          SMARTWorkspaceFilter() {
      
          }
      
          @Override
          public boolean accept(File file) {
              log.debug("Testing file: " + file.getName());
              // have we selected a directory
              if(file.isDirectory()) {
                  File[] files = file.listFiles();
                  // for all files in the directory
                  for(File f : files) {
                      log.debug("Directory: " + f.isDirectory());
                      log.debug("Name: " + f.getName());
                      // if the name is the name of the special file, return true
                      if(f.getName().equals(fileNameFilter)) {
                          return true;
                      }
                  }
              }
      
              // else, return false
              return false;
          }
      
          @Override
          public String getDescription() {
              return description;
          }
      }
      

      【讨论】:

      • 我做了这些更改,但问题是如果我的工作区文件夹存在于 C://Folder1/Folder2/workspace 并且 FileChooser 从 C:// 开始,那么过滤器将阻止导航到“工作区”因为 Folder1 和 Folder2 不包含特殊文件。我想我的问题不是很清楚。
      • 然后将 FileChooser 的基本路径设置为System.getProperty("user.dir")。这可确保它始终从您运行应用程序的文件夹中打开(这也是 eclipse/NetBeans/etc 中未编译项目的工作区)。问题是你不能允许普通文件夹也不允许它们被选中。正如@SebastianH 所说,并非没有考虑扩展JFileChooser 本身。
      【解决方案3】:

      最终@SebastianH 是正确的,通过 FileFilter 似乎是不可能的。相反,我扩展了 JFileChooser。

      javax.swing.JFileChooser fileChooser = new javax.swing.JFileChooser(defaultLocation){
          @Override
          public boolean isDirectorySelectionEnabled() {
              setOpenButtonState(this, false);
      
              File file = getSelectedFile();
      
              if(file == null){
                  return false;
              }
      
              if(file.isDirectory()){
                  File[] files = file.listFiles();
                  for(File f : files){
                      if(f.isFile() && f.getName().equals("smart.workspace")){
                          setOpenButtonState(this, true);
                          return true;
                      }
                  }
              }
      
              return false;
          }
      
          private void setOpenButtonState(java.awt.Container c, boolean flag) {
              int len = c.getComponentCount();
              for (int i = 0; i < len; i++) {
                  java.awt.Component comp = c.getComponent(i);
      
                  if (comp instanceof javax.swing.JButton) {
                      javax.swing.JButton b = (javax.swing.JButton)comp;
      
                      if ( b != null && b.getText() != null && b.getText().equals("Open") ) {
                          b.setEnabled(flag);
                      }
      
                  } else if (comp instanceof java.awt.Container) {
                      setOpenButtonState((java.awt.Container) comp, flag);
                  }
              }     
          }
      
      };
      

      除了阻止选择之外,我还添加了禁用“打开”按钮以避免混淆。

      感谢禁用打开按钮 --> Disable Open button in JFileChooser?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-28
        • 2021-01-30
        • 2011-01-25
        • 2014-02-05
        • 2013-07-04
        相关资源
        最近更新 更多