Java:强制JFileChooser仅浏览一个目录及其子文件夹

4

我创建了一个JFileChooser,并希望将其限制user.home目录及其子文件夹中。

我的JFileChooser的选择模式为仅限目录

到目前为止,我已经使用了以下代码:

//JButton select = new JButton();
final File directorylock = new File(System.getProperty("user.home"));
JFileChooser browse = new JFileChooser(directorylock);
browse.setFileView(new FileView() {
    @Override
    public Boolean isTraversable(File f) {
         return directorylock.equals(f);
    }
});

但是每次我打开JFileChooser时,它只显示用户主目录,而不是它的子文件夹,因此我无法访问或选择它们。

应该如何工作:打开JFileChooser并显示具有所有子文件夹的用户主目录。能够访问子文件夹并选择它们。不能访问用户主目录的父文件夹。

我希望这里有人知道应该如何完成! :) 预先感谢大家:D

为了更快地获得帮助,请发布一个[MCVE]或简短,自包含,正确的示例 - Andrew Thompson
@AndrewThompson 我已经尽力解释我的问题和我想要做的事情。对于任何不便我感到抱歉。 - Andreas Neophytou
@AndreasNeophytou 或许你可以使用这个链接 https://dev59.com/D2Ml5IYBdhLWcg3wqIdh 来改进Vishal的解决方案。 - RubioRic
3个回答

3

请查看Single Root File Chooser

您只会在组合框中看到指定的单个文件,以免让用户混淆您可以选择父目录。

然后,当创建类时,您只能选择指定文件夹或子文件夹中的文件。


不错,但页面上写着“使用此方法需自负风险”。可能会有危险。;-P(开个玩笑) - RubioRic
谢谢,这个有效了。我修改了他们的代码以适应我的需求,并且还必须禁用JFileChooser的文本字段,以便无法访问超级目录或父目录。谢谢 :) - Andreas Neophytou

2
请参考这个示例,它的效果很好,就像你想要的那样。
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileView;

public class JFileChooserExample {

       private JFrame mainFrame;
       private JLabel headerLabel;
       private JLabel statusLabel;
       private JPanel controlPanel;

       public JFileChooserExample(){
          prepareGUI();
       }

       public static void main(String[] args){
           JFileChooserExample  swingControlDemo = new JFileChooserExample();      
          swingControlDemo.showFileChooserDemo();
       }

       private void prepareGUI(){
          mainFrame = new JFrame("Java Swing Examples");
          mainFrame.setSize(400,400);
          mainFrame.setLayout(new GridLayout(3, 1));
          mainFrame.addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent windowEvent){
                System.exit(0);
             }        
          });    
          headerLabel = new JLabel("", JLabel.CENTER);        
          statusLabel = new JLabel("",JLabel.CENTER);    

          statusLabel.setSize(350,100);

          controlPanel = new JPanel();
          controlPanel.setLayout(new FlowLayout());

          mainFrame.add(headerLabel);
          mainFrame.add(controlPanel);
          mainFrame.add(statusLabel);
          mainFrame.setVisible(true);  
       }

       private void showFileChooserDemo(){
          headerLabel.setText("Control in action: JFileChooser"); 

          final File directorylock = new File(System.getProperty("user.home"));
          final JFileChooser  fileDialog = new JFileChooser(directorylock);

          fileDialog.setFileView(new FileView() {
                @Override
                public Boolean isTraversable(File f) {
                     return directorylock.equals(f);
                }
            });

          JButton showFileDialogButton = new JButton("Open File");
          showFileDialogButton.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
                int returnVal = fileDialog.showOpenDialog(mainFrame);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                   java.io.File file = fileDialog.getSelectedFile();
                   statusLabel.setText("File Selected :" 
                   + file.getName());
                }
                else{
                   statusLabel.setText("Open command cancelled by user." );           
                }      
             }
          });
          controlPanel.add(showFileDialogButton);
          mainFrame.setVisible(true);  
       }
    }

输出:

输入图片说明


谢谢你提供这个例子,我测试过了,它可以工作!唯一的问题(不是你代码的问题)是我想要能够访问子目录,而不仅仅是父文件夹。我想要能够访问用户目录下的每个“子”文件夹。 - Andreas Neophytou
@YassinHajaj 是的,我确定,父级不会被访问。 - Vishal Gajera
@YassinHajaj 请理解,我们无法访问父级,但可以访问子级...!! - Vishal Gajera
问题在于父目录显示在组合框中,因此用户会认为他们能够选择不同的目录。这使得用户界面变得混乱。 - camickr

2

稍加修改,我认为Vishal Gajera的解决方案可能可行。 我从tsauerwein提供的检查文件是否在(子)目录中中复制了一个方法。

   /**
    * Checks, whether the child directory is a subdirectory of the base 
    * directory.
    *
    * @param base the base directory.
    * @param child the suspected child directory.
    * @return true, if the child is a subdirectory of the base directory.
    * @throws IOException if an IOError occured during the test.
    */
   public boolean isSubDirectory(File base, File child) {

       boolean res = false;

       try {
        base = base.getCanonicalFile();
           child = child.getCanonicalFile();

           File parentFile = child;
           while (!res && parentFile != null) {
               if (base.equals(parentFile)) {
                   res = true;
               }
               parentFile = parentFile.getParentFile();
           }
       } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }

       return res;
   }


 private void showFileChooserDemo(){
      headerLabel.setText("Control in action: JFileChooser"); 

      final File directorylock = new File(System.getProperty("user.home"));
      final JFileChooser  fileDialog = new JFileChooser(directorylock);

      fileDialog.setFileView(new FileView() {
            @Override
            public Boolean isTraversable(File f) {
                 return isSubDirectory(directorylock, f);
            }
        });

      JButton showFileDialogButton = new JButton("Open File");
      showFileDialogButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            int returnVal = fileDialog.showOpenDialog(mainFrame);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
               java.io.File file = fileDialog.getSelectedFile();
               statusLabel.setText("File Selected :" 
               + file.getName());
            }
            else{
               statusLabel.setText("Open command cancelled by user." );           
            }      
         }
      });
      controlPanel.add(showFileDialogButton);
      mainFrame.setVisible(true);  
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接