2009-02-27 4 views
9

私はJavaでダイアグラムエディタを作成しています。このアプリには、.jpg、.pngなどのさまざまな標準画像形式にエクスポートするオプションがあります。ユーザーが[ファイル] - [エクスポート]をクリックするとFileFilter.jpg.pngなどになるが表示されます。今ここにJFileChooserで選択したFile to FileFilterを調整します

は私の質問です:

は、選択したファイルフィルタに調整し、デフォルトの拡張子を持ってする方法はありますか?例えば。ドキュメントの名前が "lolcat"の場合、pngフィルタが選択されている場合はデフォルトオプションが "lolcat.png"で、ユーザーがjpgファイルフィルタを選択した場合、デフォルトは自動的に "lolcat.jpg"に変更されます。

これは可能ですか?どうしたらいいですか?

編集: 以下の回答に基づいて、私はいくつかのコードを書いています。しかし、それはまだかなりうまくいきません。 propertyChangeListenerFILE_FILTER_CHANGED_PROPERTYに追加しましたが、この方法ではgetSelectedFile()がnullを返すようです。ここにコードがあります。

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(); 
      } 
     });  
    } 
} 

答えて

11

あなたが適切setSelectedFile()を使用して、選択したファイルの拡張子を変更、その後、FILE_FILTER_CHANGED_PROPERTY財産上の変更のためにJFileChooserを聞くことができるように見えます。


編集:正しいですが、この解決法は機能しません。ファイルフィルタが変更されると、そのファイルタイプが新しいフィルタと一致しないと、選択されたファイルが削除されます。だからこそ、あなたがを取得しようとしているのは、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)); 
    } 
}); 
0

getAbsolutePath(の使用):私はJFileChooserを書いていた場合、ユーザーが使用するファイルを選択し、「保存」をクリックした後、私は通常、拡張子を追加します現在のディレクトリ。 別のFileFilterを選択したときに、 "My documents"ディレクトリを表示する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)); 
      } 
     } 
    }); 
0

ここでは、この時の私の試みです。 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(); 
     } 
    }; 
4

サフィックスを付加する前にSELECTED_FILE_CHANGED_PROPERTYでPropertyChangeListenerを使用することもできます。選択されたファイルが新しいフィルタに対してチェックされた後にnullに設定されると、の前にSELECTED_FILE_CHANGED_PROPERTYイベントが実際にFILE_FILTER_CHANGED_PROPERTYイベントのの前に発生します。

evt.getOldValue()!= nullおよびevt.getNewValue()== nullの場合、JFileChooserがファイルを破棄したことがわかります。(上記のように((File)evt.getOldValue())。getName()を使って古いファイルの名前を取得し、標準の文字列解析関数を使って拡張を抜き取って、クラス内の名前付きメンバ変数に隠します。

このように、FILE_FILTER_CHANGEDイベントが発生したとき(すぐ後で、私が知る限り)、その名前のメンバ変数から隠したルート名を取得し、新しいファイルフィルタタイプの拡張子を適用して、それに応じてJFileChooserの選択したファイル

3

これはどう:ここ

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

が私の解決策であり、それは正常に動作します。それは誰かを助けるかもしれない。独自の "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(); 
     } 
    } 
} 
2

ここでは、現在のファイル名(文字列として)を取得する方法があります。

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)); 
    } 
}); 

javax.swing.plaf.basic.BasicFileChooserUIgetFileName()方法(FileChooserUIの子孫がJFileChooser.getUI()で返される)で入力するために使用されるダイアログのテキストボックスの内容を返します。JFileChooser.FILE_FILTER_CHANGED_PROPERTYのためのあなたのプロパティ変更リスナーでは、次の電話をかけますファイル名この値は常にnull以外のStringに設定されているようです(ボックスが空の場合は空の文字列を返します)。一方、getSelectedFile()は、ユーザーが既存のファイルをまだ選択していない場合はnullを返します。

ダイアログのデザインは「ファイル選択」の概念によって管理されているようです。つまり、ダイアログが表示されている間に、ユーザーが既に既存のファイルまたはsetSelectedFile()というプログラムを選択した場合にのみ、有意義な値を返します。 getSelectedFile()は、ユーザが承認した(つまりOK)ボタンをの後に入力したものをに返します。

このテクニックは単一選択のダイアログボックスでのみ機能しますが、選択したフィルタに基づいてファイル拡張子を変更することは、単一ファイル(「名前を付けて保存...」ダイアログなど)にも意味があります。

このデザインは、sun.comの2003年の討論の対象でした。詳しくは、linkを参照してください。

関連する問題