重新利用JFileChooser [英] Repurposing JFileChooser

查看:55
本文介绍了重新利用JFileChooser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在我的应用程序中实现文件浏览功能,虽然我知道可以制作一个JList项并手动执行,但我有一个想法就是为此实现JFileChooser.我设法将JFileChooser缩小为目录和文件列表,但无法覆盖其中的某些功能.我一直在查看源代码,但没有运气.我的想法是按以下方式进行处理:在列表的顶部具有/...目录,因此在单击该目录时,它会返回到父文件夹.同样,双击目录会将其设置为当前目录.双击文件后,它将返回选定的文件.

I need to implement file browsing feature in my app and while I am aware of possibility of making a JList item and doing it manually I had an idea to just implement JFileChooser for this. I managed to reduce the JFileChooser just to list of directories and files but I wasn't able to override some of it's functionalities. I have been going through source code but no luck. My idea is for it to handle as following: On the top of the list to have a /... directory so when clicked on it it returns to parent folder. Also when double clicked on directory it sets it as current directory. When double clicked on file it returns the file as selected.

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

This is the code I used so far:

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中,但这没有用.

I tried adding custom MouseListener to the JFileChooser but it didn't work.

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

This is the result I have so far:

有什么想法可以覆盖/替换哪些类或侦听器,这样我可以达到2种期望的效果吗?

Any idea which classes or listeners to overwrite/replace so I can achieve 2 desired effects?

这就是我在视觉上寻找的东西:

This is what I am looking for in visual terms:

推荐答案

在列表顶部有一个/...目录,因此在单击i时 它返回到父文件夹.

On the top of the list to have a /... directory so when clicked on i it returns to parent folder.

JFileChooser具有名称为changeToParentDirectory()的方法.因此,您只需添加一个Button并调用该方法即可.

JFileChooser has method with name changeToParentDirectory(). So you could simply add a Button and call that method.

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

还双击目录会将其设置为当前目录.

Also when double clicked on directory it sets it as current directory.

您可以将PropertyChangeListener设置为侦听JFileChooser.DIRECTORY_CHANGED_PROPERTY属性,该属性会在使用双击或内部命令更改了当前目录时触发.

You can set a PropertyChangeListener to listen for JFileChooser.DIRECTORY_CHANGED_PROPERTY property that is fired whenever the current directory has changed using double click or the internal commands.

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());
        }
    }   
});

双击文件会返回所选文件.

When double clicked on file it returns the file as selected.

您可以将ActionListener设置为侦听双击选择文件时触发的JFileChooser.APPROVE_SELECTION操作.

You can set an ActionListener to listen for JFileChooser.APPROVE_SELECTION action that is fired whenever a file is chosen by double click.

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());
        }   
    }   
});


您误解了我对父文件夹操作的理解. 这是图片 描述它.

这可以通过使用受操纵的FileSystemViewJFileChooser来实现,该cc负责与文件系统的内容进行交互.我的实现操纵getFiles方法在列表中走私特殊的File,该列表具有已定义的名称并指向父目录.
我不太确定这是否是个好主意,因为这实际上并不意味着要包含在JFileChooser代码中,但是我们可以开始了.

This could be achieved by using a manipulated FileSystemView with the JFileChooser that is responsible for interacting with the content of the filesystem. My implementation manipulates the getFiles method to smuggle a special File in the list that has a defined name and points to the parent directory.
I'm not quite sure if this is a very good idea, since this is really not meant to be in the JFileChooser Code but here we go.

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();
    }   
});

有没有一种快速的解决方案可以将滚动从水平方向设置为垂直 JFileChooser?

is there a quick solution to set scroll from horizontal to vertical for JFileChooser?

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

There are two possibilities. The simple one is to change the style of your JFileChooser to the Details View by adding this code:

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

更复杂的方法是更改​​文件视图JListLayoutOrientation,该文件视图是sun.swing.FilePane的组成部分,而sun.swing.FilePaneComponent,而JFileChooserJFileChooser中.
这里的一个问题是FilePane不是Java库的一部分,而是Core库的一部分,并且默认情况下不可访问.但是您可以使用Reflection在FilePane中获取字段private JList list;,并使用以下代码将其LayoutOrientation更改为JList.VERTICAL:

The more complex one is to change the LayoutOrientation of the file view JList that is a component of sun.swing.FilePane that is the Component with ID:2 in the JFileChooser.
One problem here is that FilePane is not part of the Java Library but part of the Core Library and not accessible by default. But you can use Reflection to get the field private JList list; in the FilePane and change its LayoutOrientation to JList.VERTICAL with this code:

// 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);

这篇关于重新利用JFileChooser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆