java - 如何在 JFileChooser Swing 组件中列出最近使用的文件

标签 java swing list jfilechooser

我在 Java 项目中使用 javax.swing.JFileChooser swing 组件通过对话框打开文件。如何在 JFileChooser 中列出最近使用的文件以供选择。每次我都要进入目录并选择文件,这很耗时。

如何在组件本身中列出最后几个最近使用的文件,以便我们不需要一次又一次地浏览目录来选择文件?

最佳答案

JFileChooser 允许您提供添加到右侧 JFileChooser 组件的 accessory Component Windows 下的一侧。

你能做的是......

  • 创建 JListListModel,将 JList 设置为 JFileChoosers accessory(将其包装在 JScrollPane 中)
  • 每次选择文件时,将其添加到
  • 每次打开 JFileChooser 时,请使用 Set 中的值更新 JList 的模型(或返回模型)与设置)。
  • 每次用户从列表中选择一个值时,您都需要更改 JFileChoosers selectedFile 属性以反射(reflect)更改...

更多详情,请查看Providing an Accessory Component了解更多详情...

已更新

Example

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileSystemView;

public class TestFileChooser {

    public static void main(String[] args) {
        new TestFileChooser();
    }

    public TestFileChooser() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JFileChooser fc;
        private RectentFileList rectentFileList;

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton chooser = new JButton("Choose");
            chooser.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (fc == null) {
                        fc = new JFileChooser();
                        rectentFileList = new RectentFileList(fc);
                        fc.setAccessory(rectentFileList);
                        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    }
                    switch (fc.showOpenDialog(TestPane.this)) {
                        case JOptionPane.OK_OPTION:
                            File file = fc.getSelectedFile();
                            rectentFileList.add(file);
                            break;
                    }
                }
            });
            add(chooser);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }

    public class RectentFileList extends JPanel {

        private final JList<File> list;
        private final FileListModel listModel;
        private final JFileChooser fileChooser;

        public RectentFileList(JFileChooser chooser) {
            fileChooser = chooser;
            listModel = new FileListModel();
            list = new JList<>(listModel);
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setCellRenderer(new FileListCellRenderer());

            setLayout(new BorderLayout());
            add(new JScrollPane(list));

            list.addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e) {
                    if (!e.getValueIsAdjusting()) {
                        File file = list.getSelectedValue();
                        // You might like to check to see if the file still exists...
                        fileChooser.setSelectedFile(file);
                    }
                }
            });
        }

        public void clearList() {
            listModel.clear();
        }

        public void add(File file) {
            listModel.add(file);
        }

        public class FileListModel extends AbstractListModel<File> {

            private List<File> files;

            public FileListModel() {
                files = new ArrayList<>();
            }

            public void add(File file) {
                if (!files.contains(file)) {
                    if (files.isEmpty()) {
                        files.add(file);
                    } else {
                        files.add(0, file);
                    }
                    fireIntervalAdded(this, 0, 0);
                }
            }

            public void clear() {
                int size = files.size() - 1;
                if (size >= 0) {
                    files.clear();
                    fireIntervalRemoved(this, 0, size);
                }
            }

            @Override
            public int getSize() {
                return files.size();
            }

            @Override
            public File getElementAt(int index) {
                return files.get(index);
            }
        }

        public class FileListCellRenderer extends DefaultListCellRenderer {

            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (value instanceof File) {
                    File file = (File) value;
                    Icon ico = FileSystemView.getFileSystemView().getSystemIcon(file);
                    setIcon(ico);
                    setToolTipText(file.getParent());
                    setText(file.getName());
                }
                return this;
            }

        }

    }

}

持久性问题是一个广泛的问题,将取决于您的个人需求,例如,您可以将文件列表转储到平面文件中,这可能是最简单的解决方案,因为这意味着您可以简单地读取从头到尾查看文件并知道您拥有全部内容。此外,再次写出文件将覆盖以前的任何值,从而易于管理。

其他解决方案可能需要提供“count”属性,然后将其添加到已知键后以列出值,这需要在更新详细信息时手动删除旧值。您还可以尝试使用分隔符将所有值保存为持久性存储中的单个值,但这会带来选择不在文件名中使用的分隔符的问题(路径分隔符可能会这样做:D)

看看How can I save the state of my program and then load it?获取更多想法...

已更新

经过一番思考,您可以使用 Preferences API 通过使用 File.pathSeparator 使用单个键来存储文件列表,因为这应该是唯一的并且不被文件名/路径使用。

例如,您可以使用以下内容保存列表......

StringBuilder sb = new StringBuilder(128);
for (int index = 0; index < listModel.getSize(); index++) {
    File file = listModel.getElementAt(index);
    if (sb.length() > 0) {
        sb.append(File.pathSeparator);
    }
    sb.append(file.getPath());
}
System.out.println(sb.toString());
Preferences p = Preferences.userNodeForPackage(TestFileChooser.class);
p.put("RectentFileList.fileList", sb.toString());

然后使用诸如...之类的东西再次加载它

Preferences p = Preferences.userNodeForPackage(TestFileChooser.class);
String listOfFiles = p.get("RectentFileList.fileList", null);
if (listOfFiles != null) {
    String[] files = listOfFiles.split(File.pathSeparator);
    for (String fileRef : files) {
        File file = new File(fileRef);
        if (file.exists()) {
            add(file);
        }
    }
}

关于java - 如何在 JFileChooser Swing 组件中列出最近使用的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25051305/

相关文章:

python - 将数字分解为其他数字

python - 在Python中使用列表的程序

list - 如何在 Go 中打印列表的值

java - 整个代码私有(private)静态

java - 如何让这个 FlowLayout 包裹在它的 JSplitPane 中?

java - 如何在 swing 中使用 JFileChooser 浏览仅扩展名为 .xls 的文件

java - JFormattedTextField 破坏 DocumentFilter

java - 使用领域驱动设计在后端和前端重复逻辑

java - 如何在android中将日期和时间转换为est格式?

java - RecyclerView 未显示任何项目