重新利用JFileChooser

时间:2016-03-08 15:03:59

标签: java swing jfilechooser

我需要在我的应用程序中实现文件浏览功能,虽然我知道有可能制作一个JList项目并手动执行,但我有一个想法就是为此实现JFileChooser。我设法将JFileChooser简化为目录和文件列表,但我无法覆盖其中的一些功能。我一直在浏览源代码,但没有运气。我的想法是它处理如下:在列表的顶部有一个/ ...目录所以当点击它时它返回到父文件夹。此外,当双击目录时,它将其设置为当前目录。双击文件时,它会将文件返回为选中状态。

这是我到目前为止使用的代码:

final JFileChooser fc = new JFileChooser();
fc.setControlButtonsAreShown(false);
fc.setCurrentDirectory(paths[list.getSelectedIndex()]);
/*remove unwanted components*/
for(int i = 0; i < fc.getComponentCount(); i++) {
    fc.getComponent(0).setVisible(false);
    fc.getComponent(1).setVisible(false);
    fc.getComponent(3).setVisible(false);
}
add(fc, BorderLayout.CENTER);

我尝试将自定义MouseListener添加到JFileChooser但它没有用。

这是我到目前为止的结果:

enter image description here

知道哪些类或听众要覆盖/替换所以我可以实现2个想要的效果?

这就是我用视觉术语寻找的东西:

enter image description here

1 个答案:

答案 0 :(得分:3)

  

在列表的顶部有一个/ ...目录所以当点击i时   它返回父文件夹。

JFileChooser包含名为changeToParentDirectory()的方法。所以你可以简单地添加一个Button并调用该方法。

JButton toParent = new JButton("/..");
toParent.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent a) {
        fc.changeToParentDirectory();
    }
});
fc.add(toParent, BorderLayout.NORTH);
  

当双击目录时,它将其设置为当前目录。

您可以设置PropertyChangeListener以侦听当使用双击或内部命令更改当前目录时触发的JFileChooser.DIRECTORY_CHANGED_PROPERTY属性。

fc.addPropertyChangeListener(new PropertyChangeListener(){
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String command = e.getPropertyName();
        if (command.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
            File currentDir = fc.getCurrentDirectory();
            System.out.println(currentDir.getAbsolutePath());
        }
    }   
});
  

双击文件时,它会将文件返回为选中状态。

您可以设置ActionListener来监听通过双击选择文件时触发的JFileChooser.APPROVE_SELECTION操作。

fc.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command.equals(JFileChooser.APPROVE_SELECTION)) {
            File selectedFile = fc.getSelectedFile();
            System.out.println(selectedFile.getAbsolutePath());
        }   
    }   
});


编辑:

  

你误解我的父文件夹操作。 Here is an image   描述它。

这可以通过使用负责与文件系统内容交互的FileSystemView的操作JFileChooser来实现。我的实现操作getFiles方法来走私列表中具有已定义名称并指向父目录的特殊File
我不太确定这是否是一个非常好的主意,因为这实际上并不属于JFileChooser代码,而是我们去了。

fc.setFileSystemView(new FileSystemView(){
    // this method is abstract but since you don't
    // want to create directories here you don't 
    // need to implement it.
    @Override
    public File createNewFolder(File f) throws IOException {
        return null;
    }

    // manipulate the default getFiles method that creates
    // the list of files in the current directory
    @Override
    public File[] getFiles(File dir, boolean useFileHiding){
        // get the list of files from default implementation
        File[] files = super.getFiles(dir,useFileHiding);
        // get the parent directory of current
        File parent = getParentDirectory(dir);
        // skip the next for problematic folders with
        // empty names and root folders
        if(!dir.getName().isEmpty() && !isRoot(dir)){
            // create a new list of files with one extra place
            File[] nfiles = new File[files.length + 1];
            // add a special file to list that points to parent directory
            nfiles[0] = new File(parent.getAbsolutePath()){
                // set a special name for that file
                @Override
                    public String getName(){return "...";}
                };
            // add the rest of files to list
            for(int i = 0; i < files.length; i++)
                nfiles[i+1] = files[i];
            // use the new list
            files = nfiles; 
        }
        // return list of files
        return files;
    }

    // some special folders like "c:" gets converted
    // in shellfolders.Then our setted name "..." would
    // get converted to "local drive (c:)". This garantees
    // that our setted name will be used.
    @Override
    public String getSystemDisplayName(File f) {
        return f.getName();
    }   
});

EDIT2:

  

是否有快速解决方案将滚动设置为从水平到垂直   对于JFileChooser?

有两种可能性。简单的方法是通过添加以下代码将JFileChooser的样式更改为Details View

Action details = fc.getActionMap().get("viewTypeDetails");
details.actionPerformed(null);

更复杂的是更改文件视图LayoutOrientation的{​​{1}},JListsun.swing.FilePane的组件ComponentID:2 in JFileChooser FilePane 这里的一个问题是private JList list;不是Java库的一部分,而是核心库的一部分,默认情况下不可访问。但您可以使用反射来获取FilePane中的字段LayoutOrientation,并使用以下代码将其JList.VERTICAL更改为// get the FilePane Component of JFileChooser Object filepane = fc.getComponent(2); // get the list field with reflection Field field_list = filepane.getClass().getDeclaredField("list"); // get access to this private field field_list.setAccessible(true); // read the value of the field JList<?> list = (JList<?>)field_list.get(filepane); // change the layout orientation list.setLayoutOrientation(JList.VERTICAL);

abstract class Vehicle {
  // Some vars

  public abstract void draw();
}

class Car : Vehicle {
  // Some vars

  public override void draw() { /* Draw function */ }
}

class Truck : Vehicle {
  // Some vars

  public override void draw() { /* Another draw function */ }
}