重新利用 JFileChooser
Repurposing JFileChooser
我需要在我的应用程序中实现文件浏览功能,虽然我知道制作 JList 项目并手动执行它的可能性,但我有一个想法为此实现 JFileChooser。我设法将 JFileChooser 缩减为目录和文件列表,但我无法覆盖它的某些功能。我一直在浏览源代码,但没有运气。我的想法是按如下方式处理:在列表的顶部有一个 /... 目录,因此当单击它时它 returns 到父文件夹。此外,当双击目录时,它会将其设置为当前目录。当双击文件时,它 returns 文件被选中。
这是我目前使用的代码:
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,但没有成功。
这是我目前的结果:
知道 类 或听众 overwrite/replace 可以达到 2 个预期效果吗?
这就是我在视觉方面寻找的东西:
On the top of the list to have a /... directory so when clicked on i
it returns to parent folder.
JFileChooser
有名称为 changeToParentDirectory()
的方法。所以您可以简单地添加一个 Button 并调用该方法。
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
属性,当使用双击或内部命令更改当前目录时触发。
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
每当双击选择文件时触发的操作。
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());
}
}
});
编辑:
you misunderstood me for the parent folder action. Here is an image
to describe it.
这可以通过使用一个被操纵的 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();
}
});
编辑 2:
is there a quick solution to set scroll from horizontal to vertical
for JFileChooser?
有两种可能。最简单的方法是通过添加以下代码将 JFileChooser
的样式更改为 Details View
:
Action details = fc.getActionMap().get("viewTypeDetails");
details.actionPerformed(null);
更复杂的是更改文件视图 JList
的 LayoutOrientation
,它是 sun.swing.FilePane
的一个组件,即 Component
和 ID:2
在 JFileChooser
.
这里的一个问题是 FilePane
不是 Java 库的一部分,而是核心库的一部分,默认情况下不可访问。但是您可以使用反射获取 FilePane
中的字段 private JList list;
并使用以下代码将其 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);
我需要在我的应用程序中实现文件浏览功能,虽然我知道制作 JList 项目并手动执行它的可能性,但我有一个想法为此实现 JFileChooser。我设法将 JFileChooser 缩减为目录和文件列表,但我无法覆盖它的某些功能。我一直在浏览源代码,但没有运气。我的想法是按如下方式处理:在列表的顶部有一个 /... 目录,因此当单击它时它 returns 到父文件夹。此外,当双击目录时,它会将其设置为当前目录。当双击文件时,它 returns 文件被选中。
这是我目前使用的代码:
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,但没有成功。
这是我目前的结果:
知道 类 或听众 overwrite/replace 可以达到 2 个预期效果吗?
这就是我在视觉方面寻找的东西:
On the top of the list to have a /... directory so when clicked on i it returns to parent folder.
JFileChooser
有名称为 changeToParentDirectory()
的方法。所以您可以简单地添加一个 Button 并调用该方法。
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
属性,当使用双击或内部命令更改当前目录时触发。
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
每当双击选择文件时触发的操作。
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());
}
}
});
编辑:
you misunderstood me for the parent folder action. Here is an image to describe it.
这可以通过使用一个被操纵的 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();
}
});
编辑 2:
is there a quick solution to set scroll from horizontal to vertical for JFileChooser?
有两种可能。最简单的方法是通过添加以下代码将 JFileChooser
的样式更改为 Details View
:
Action details = fc.getActionMap().get("viewTypeDetails");
details.actionPerformed(null);
更复杂的是更改文件视图 JList
的 LayoutOrientation
,它是 sun.swing.FilePane
的一个组件,即 Component
和 ID:2
在 JFileChooser
.
这里的一个问题是 FilePane
不是 Java 库的一部分,而是核心库的一部分,默认情况下不可访问。但是您可以使用反射获取 FilePane
中的字段 private JList list;
并使用以下代码将其 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);