настроить выбранный файл в FileFilter в JFileChooser - PullRequest
10 голосов
/ 27 февраля 2009

Я пишу редактор диаграмм в Java. Это приложение имеет возможность экспортировать в различные стандартные форматы изображений, такие как .jpg, .png и т. Д. Когда пользователь нажимает Файл-> Экспорт, вы получаете JFileChooser, который имеет число FileFilter с, для .jpg, .png и т. Д.

Теперь вот мой вопрос:

Есть ли способ настроить расширение по умолчанию для выбранного фильтра файлов? Например. если документ называется «lolcat», то по умолчанию параметр должен быть «lolcat.png», когда выбран фильтр png, и когда пользователь выбирает фильтр файлов jpg, значение по умолчанию должно автоматически измениться на «lolcat.jpg». *

Возможно ли это? Как я могу это сделать?

редактирование: Основываясь на ответе ниже, я написал некоторый код. Но это еще не совсем работает. Я добавил propertyChangeListener к FILE_FILTER_CHANGED_PROPERTY, но кажется, что в этом методе getSelectedFile() возвращает ноль. Вот код

package nl.helixsoft;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileFilter;

public class JFileChooserTest {
    public class SimpleFileFilter extends FileFilter {
        private String desc;
        private List<String> extensions;
        private boolean showDirectories;

        /**
         * @param name example: "Data files"
         * @param glob example: "*.txt|*.csv"
         */
        public SimpleFileFilter (String name, String globs) {
            extensions = new ArrayList<String>();
            for (String glob : globs.split("\\|")) {
                if (!glob.startsWith("*.")) 
                    throw new IllegalArgumentException("expected list of globs like \"*.txt|*.csv\"");
                // cut off "*"
                // store only lower case (make comparison case insensitive)
                extensions.add (glob.substring(1).toLowerCase());
            }
            desc = name + " (" + globs + ")";
        }

        public SimpleFileFilter(String name, String globs, boolean showDirectories) {
            this(name, globs);
            this.showDirectories = showDirectories;
        }

        @Override
        public boolean accept(File file) {
            if(showDirectories && file.isDirectory()) {
                return true;
            }
            String fileName = file.toString().toLowerCase();

            for (String extension : extensions) {   
                if (fileName.endsWith (extension)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public String getDescription() {
            return desc;
        }

        /**
         * @return includes '.'
         */
        public String getFirstExtension() {
            return extensions.get(0);
        }
    }

    void export() {
        String documentTitle = "lolcat";

        final JFileChooser jfc = new JFileChooser();
        jfc.setDialogTitle("Export");
        jfc.setDialogType(JFileChooser.SAVE_DIALOG);
        jfc.setSelectedFile(new File (documentTitle));
        jfc.addChoosableFileFilter(new SimpleFileFilter("JPEG", "*.jpg"));
        jfc.addChoosableFileFilter(new SimpleFileFilter("PNG", "*.png"));
        jfc.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent arg0) {
                System.out.println ("Property changed");
                String extold = null;
                String extnew = null;
                if (arg0.getOldValue() == null || !(arg0.getOldValue() instanceof SimpleFileFilter)) return;
                if (arg0.getNewValue() == null || !(arg0.getNewValue() instanceof SimpleFileFilter)) return;
                SimpleFileFilter oldValue = ((SimpleFileFilter)arg0.getOldValue());
                SimpleFileFilter newValue = ((SimpleFileFilter)arg0.getNewValue());
                extold = oldValue.getFirstExtension();
                extnew = newValue.getFirstExtension();
                String filename = "" + jfc.getSelectedFile();
                System.out.println ("file: " + filename + " old: " + extold + ", new: " + extnew);
                if (filename.endsWith(extold)) {
                    filename.replace(extold, extnew);
                } else {
                    filename += extnew;
                }
                jfc.setSelectedFile(new File (filename));
            }
        });
        jfc.showDialog(frame, "export");
    }

    JFrame frame;

    void run() {
        frame = new JFrame();
        JButton btn = new JButton ("export");
        frame.add (btn);
        btn.addActionListener (new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                export();
            }
        });
        frame.setSize (300, 300);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {     
            public void run() {
                JFileChooserTest x =  new JFileChooserTest();
                x.run();
            }
        });     
    }
}

Ответы [ 7 ]

11 голосов
/ 27 февраля 2009

Похоже, что вы можете прослушать JFileChooser для изменения свойства FILE_FILTER_CHANGED_PROPERTY, а затем соответствующим образом изменить расширение выбранного файла, используя setSelectedFile().


РЕДАКТИРОВАТЬ: Вы правы, это решение не работает. Оказывается, что при изменении фильтра файлов выбранный файл удаляется, если его тип файла не соответствует новому фильтру. Вот почему вы получаете null при попытке getSelectedFile().

Рассматривали ли вы добавление расширения позже? Когда я пишу JFileChooser, я обычно добавляю расширение после того, как пользователь выбрал файл для использования и нажал «Сохранить»:

if (result == JFileChooser.APPROVE_OPTION)
{
  File file = fileChooser.getSelectedFile();
  String path = file.getAbsolutePath();

  String extension = getExtensionForFilter(fileChooser.getFileFilter());

  if(!path.endsWith(extension))
  {
    file = new File(path + extension);
  }
}

fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener()
{
  public void propertyChange(PropertyChangeEvent evt)
  {
    FileFilter filter = (FileFilter)evt.getNewValue();

    String extension = getExtensionForFilter(filter); //write this method or some equivalent

    File selectedFile = fileChooser.getSelectedFile();
    String path = selectedFile.getAbsolutePath();
    path.substring(0, path.lastIndexOf("."));

    fileChooser.setSelectedFile(new File(path + extension));
  }
});
4 голосов
/ 16 января 2013

Вот мое решение, и оно отлично работает. Это может кому-то помочь. Вы должны создать свой собственный класс "MyExtensionFileFilter", в противном случае вам придется изменить код.

public class MyFileChooser extends JFileChooser {
    private File file = new File("");

    public MyFileChooser() {
        addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String filename = MyFileChooser.this.file.getName();
                String extold = null;
                String extnew = null;
                if (e.getOldValue() == null || !(e.getOldValue() instanceof MyExtensionFileFilter)) {
                    return;
                }
                if (e.getNewValue() == null || !(e.getNewValue() instanceof MyExtensionFileFilter)) {
                    return;
                }
                MyExtensionFileFilter oldValue = ((MyExtensionFileFilter) e.getOldValue());
                MyExtensionFileFilter newValue = ((MyExtensionFileFilter) e.getNewValue());
                extold = oldValue.getExtension();
                extnew = newValue.getExtension();

                if (filename.endsWith(extold)) {
                    filename = filename.replace(extold, extnew);
                } else {
                    filename += ("." + extnew);
                }
                setSelectedFile(new File(filename));
            }
        });
    }

    @Override
    public void setSelectedFile(File file) {
        super.setSelectedFile(file);
        if(getDialogType() == SAVE_DIALOG) {
            if(file != null) {
                super.setSelectedFile(file);
                this.file = file;
            }
        }
    }

    @Override
    public void approveSelection() { 
        if(getDialogType() == SAVE_DIALOG) {
            File f = getSelectedFile();  
            if (f.exists()) {  
                String msg = "File existes ...";  
                msg = MessageFormat.format(msg, new Object[] { f.getName() });  
                int option = JOptionPane.showConfirmDialog(this, msg, "", JOptionPane.YES_NO_OPTION);
                if (option == JOptionPane.NO_OPTION ) {  
                    return;  
                }
            }
        }
        super.approveSelection();   
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if(!visible) {
            resetChoosableFileFilters();
        }
    }
}
4 голосов
/ 25 ноября 2010

Как насчет этого:

class MyFileChooser extends JFileChooser {
   public void setFileFilter(FileFilter filter) {

    super.setFileFilter(filter);

    FileChooserUI ui = getUI();

    if( ui instanceof BasicFileChooserUI ) {
     BasicFileChooserUI bui = (BasicFileChooserUI) ui;

     String file = bui.getFileName();

     if( file != null ) {
      String newFileName = ... change extension 
      bui.setFileName( newFileName );
     }
    }
   }
  }
4 голосов
/ 12 августа 2010

Вы также можете использовать PropertyChangeListener в SELECTED_FILE_CHANGED_PROPERTY до добавления своего суффикса. Когда выбранный файл проверяется на соответствие новому фильтру (и впоследствии устанавливается на ноль), событие SELECTED_FILE_CHANGED_PROPERTY фактически запускается до события FILE_FILTER_CHANGED_PROPERTY.

Если evt.getOldValue ()! = Null и evt.getNewValue () == null, вы знаете, что JFileChooser уничтожил ваш файл. Затем вы можете получить имя старого файла (используя ((File) evt.getOldValue ()). GetName (), как описано выше), извлечь расширение с помощью стандартных функций синтаксического анализа строк и сохранить его в именованной переменной-члене вашего класса. .

Таким образом, когда событие FILE_FILTER_CHANGED инициируется (сразу после этого, насколько я могу определить), вы можете извлечь это спрятанное имя корня из именованной переменной-члена, применить расширение для нового типа фильтра файлов и установить Файл, выбранный JFileChooser соответственно.

2 голосов
/ 28 февраля 2013

Вот метод для получения текущего имени файла (в виде строки). В прослушивателе изменения свойства для JFileChooser.FILE_FILTER_CHANGED_PROPERTY вы делаете следующий вызов:

final JFileChooser fileChooser = new JFileChooser();
fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener()
{
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String currentName = ((BasicFileChooserUI)fileChooser.getUI()).getFileName();
        MyFileFilter filter = (MyFileFilter) e.getNewValue();

        // ... Transform currentName as you see fit using the newly selected filter.
        // Suppose the result is in newName ...

        fileChooser.setSelectedFile(new File(newName));
    }
});

Метод getFileName() для javax.swing.plaf.basic.BasicFileChooserUI (потомок FileChooserUI, возвращаемый JFileChooser.getUI()) возвращает содержимое текстового поля диалога, которое используется для ввода имени файла. Кажется, что это значение всегда установлено в ненулевую строку (она возвращает пустую строку, если поле пусто). С другой стороны, getSelectedFile() возвращает ноль, если пользователь еще не выбрал существующий файл.

Кажется, что дизайн диалога регулируется концепцией «выбора файла»; то есть, когда диалоговое окно является видимым getSelectedFile() возвращает значащее значение, только если пользователь уже выбрал существующий файл или программу с именем setSelectedFile(). getSelectedFile() вернет то, что пользователь набрал после того, как пользователь нажмет кнопку подтверждения (т.е. ОК).

Этот метод будет работать только для диалогов с одним выбором, однако изменение расширения файла на основе выбранного фильтра также должно иметь смысл только для отдельных файлов (диалоги «Сохранить как ...» или аналогичные).

Этот дизайн был предметом обсуждения на sun.com в 2003 году, подробности см. По ссылке .

0 голосов
/ 11 июня 2010

Вот моя попытка сделать это. Он использует функцию accept (), чтобы проверить, проходит ли файл фильтр. Если имени файла нет, расширение добавляется в конец.

JFileChooser jfc = new JFileChooser(getFile()) {
        public void approveSelection() {
            if (getDialogType() == SAVE_DIALOG) {
                File selectedFile = getSelectedFile();

                FileFilter ff = getFileFilter();

                // Checks against the current selected filter
                if (!ff.accept(selectedFile)) {
                    selectedFile = new File(selectedFile.getPath() + ".txt");
                }
                super.setSelectedFile(selectedFile);

                if ((selectedFile != null) && selectedFile.exists()) {
                    int response = JOptionPane.showConfirmDialog(
                            this,
                            "The file " + selectedFile.getName() + " already exists.\n" +
                            "Do you want to replace it?",
                            "Ovewrite file",
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.WARNING_MESSAGE
                    );
                    if (response == JOptionPane.NO_OPTION)
                        return;
                }
            }
            super.approveSelection();
        }
    };
0 голосов
/ 30 марта 2009

Использование getAbsolutePath () при предыдущем изменении текущего каталога. Я был удивлен, когда диалоговое окно JFileChooser, отображающее каталог «Мои документы», изменило каталог проекта Netbeans, когда я выбрал другой FileFilter, поэтому я изменил его, чтобы использовать getName (). Я также использовал JDK 6 FileNameExtensionFilter.

Вот код:

    final JFileChooser fc = new JFileChooser();
    final File sFile = new File("test.xls");
    fc.setSelectedFile(sFile);
    // Store this filter in a variable to be able to select this after adding all FileFilter
    // because addChoosableFileFilter add FileFilter in order in the combo box
    final FileNameExtensionFilter excelFilter = new FileNameExtensionFilter("Excel document (*.xls)", "xls");
    fc.addChoosableFileFilter(excelFilter);
    fc.addChoosableFileFilter(new FileNameExtensionFilter("CSV document (*.csv)", "csv"));
    // Force the excel filter
    fc.setFileFilter(excelFilter);
    // Disable All Files
    fc.setAcceptAllFileFilterUsed(false);

    // debug
    fc.addPropertyChangeListener(new PropertyChangeListener() {

        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("Property name=" + evt.getPropertyName() + ", oldValue=" + evt.getOldValue() + ", newValue=" + evt.getNewValue());
            System.out.println("getSelectedFile()=" + fc.getSelectedFile());
        }
    });

    fc.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {

        public void propertyChange(PropertyChangeEvent evt) {
            Object o = evt.getNewValue();
            if (o instanceof FileNameExtensionFilter) {
                FileNameExtensionFilter filter = (FileNameExtensionFilter) o;

                String ex = filter.getExtensions()[0];

                File selectedFile = fc.getSelectedFile();
                if (selectedFile == null) {
                    selectedFile = sFile;
                }
                String path = selectedFile.getName();
                path = path.substring(0, path.lastIndexOf("."));

                fc.setSelectedFile(new File(path + "." + ex));
            }
        }
    });
...