Я использую javax.swing.JFileChooser swing компонент в моем проекте Java для открытия файла по диалогу. Как просмотреть недавно использованные файлы для выбора в JFileChooser. Каждый раз, когда я захожу в каталог и выбираю файл, который занимает много времени.
Как перечислить последние несколько недавно использованных файлов в самом компоненте, так что нам не нужно снова и снова перемещаться по каталогам, чтобы выбрать файл?
JFileChooser
позволяет вам поставлять accessory
Component
который добавляется к компоненту JFileChooser
, с правой стороны под Windows.
Что вы можете сделать...
JList
и ListModel
, установите JList
как accessory
JFileChoosers
(JScrollPane
его в JScrollPane
)Set
JFileChooser
, обновите модель JList
со значениями из Set
(или обратно с помощью Set
).JFileChoosers
selectedFile
чтобы отразить изменение...Для получения дополнительной информации см. " Предоставление компонента аксессуаров" для получения более подробной информации...
обновленный
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)
Посмотрите, как я могу сохранить состояние своей программы и загрузить ее? для некоторых идей...
обновленный
Немного подумав, вы можете использовать API Preferences
для хранения списка файлов с помощью одного ключа с помощью File.pathSeparator
, так как это должно быть уникальным и не использоваться именем файла /path.
Например, вы можете сохранить список, используя что-то вроде...
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);
}
}
}
Use setSelectedFile(File file) method of JFileChooser.
Док говорит:
public void setSelectedFile(File file)
Устанавливает выбранный файл. Если родительский каталог файла не является текущим каталогом, изменяет текущий каталог в качестве родительского каталога файла.