代码之家  ›  专栏  ›  技术社区  ›  amarillion

在JFileChooser中将所选文件调整为FileFilter

  •  10
  • amarillion  · 技术社区  · 16 年前

    我正在用java编写一个图表编辑器。当用户单击文件->时,此应用程序可以选择导出为各种标准图像格式,如.jpg、.png等;出口,你会得到一个 JFileChooser 其中有很多 FileFilter .jpg , .png

    现在我的问题是:

    是否有办法将默认文件的扩展名调整为所选文件筛选器?例如,如果文档名为“lolcat”,则当选择png过滤器时,默认选项应为“lolcat.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 回复  |  直到 8 年前
        1
  •  12
  •   Amanda S    16 年前

    看起来你可以听音乐了 JFileChooser 换个环境 FILE_FILTER_CHANGED_PROPERTY 属性,然后使用 setSelectedFile() .


    null 当你试图 getSelectedFile()

    您考虑过以后再添加扩展吗?当我写一篇文章的时候 文件选择器

    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));
      }
    });
    
        2
  •  5
  •   Clandestino    14 年前

    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 );
         }
        }
       }
      }
    
        3
  •  4
  •   Marc Renouf    14 年前

    在附加后缀之前,还可以对选定的\u文件\u更改的\u属性使用PropertyChangeListener。当选中的文件根据新筛选器进行检查(随后设置为null)时,将实际触发选中的\u file\u CHANGED\u属性事件 之前

    如果evt.getOldValue()为null和evt.getNewValue()==null,您知道JFileChooser已经破坏了您的文件。然后,您可以获取旧文件的名称(如上所述,使用((file)evt.getOldValue()).getName()),使用标准字符串解析函数提取扩展名,并将其隐藏到类中的命名成员变量中。

    这样,当触发FILE\u FILTER\u CHANGED事件时(紧接着,尽我所能确定),您可以从命名的成员变量中提取隐藏的根名称,为新的文件筛选器类型应用扩展名,并相应地设置JFileChooser的选定文件。

        4
  •  4
  •   Tika    12 年前

    这是我的解决方案,效果很好。这也许对某人有帮助。您应该创建自己的“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();
            }
        }
    }
    
        5
  •  3
  •   amicus99    12 年前

    以下是获取当前文件名(作为字符串)的方法。在您的属性更改侦听器中 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() 如果用户尚未选择现有文件,则返回null。

    对话框的设计似乎受“文件选择”概念的支配;也就是说,对话框是可见的 getSelectedFile() 仅当用户已选择现有文件或调用的程序时,才返回有意义的值 setSelectedFile() . getSelectedFile() 将返回用户键入的内容 之后 用户单击“批准”(即“确定”)按钮。

    这一设计早在2003年就在sun.com上引起了争论,见 link 详情请参阅。

        6
  •  0
  •   Franck    16 年前

    在上一个目录中使用getAbsolutePath()会更改当前目录。 当我选择不同的文件过滤器时,显示“我的文档”目录的JFileChooser对话框更改为Netbeans的项目目录时,我感到惊讶,因此我将其更改为使用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));
                }
            }
        });
    
        7
  •  0
  •   Andy Doyle    15 年前

    这是我的尝试。它使用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();
            }
        };
    
        8
  •  0
  •   MasterHD    4 年前

    FileNameExtensionFilter 而不是 FileFilter 如果您的Java版本支持它。否则,创建自己的新的类似抽象类,该类从 文件过滤器 并且有一个附加的方法 getExtension FileNameExtensionFilter.getExtensions ).然后覆盖 getExtension 对于要使用的每个导出筛选器。

    public abstract class MyFileFilter extends FileFilter {
        abstract public String getExtension();
    }
    

    然后,对于示例JPG过滤器,您只需要覆盖一个比以前更多的方法:

        MyFileFilter filterJPG = new MyFileFilter () {
            @Override
            public String getDescription() {
                return "A JPEG image (*." + getExtension() + ")";
            }
            @Override
            public boolean accept(File f) {
                String filename = f.getName().toLowerCase();
                return filename.endsWith("."+getExtension());
            }
            @Override
            public String getExtension() { return "jpg"; }
        };
    

    用户选择文件后,只需调用 getFileFilter 要确定用户选择的过滤器,请执行以下操作:

    jfc.showDialog(frame, "export");
    File file = jfc.getSelectedFile();
    RvFileFilter filter = (RvFileFilter)jfc.getFileFilter();
    String sExt = filter.getExtension(); //The extension to ensure the file has
    

    如果你能使用 FileNameExtensionFilter.getExtensions() 然后您可以简单地使用数组中的第一个条目。