ファイル選択ダイアログの挙動を正したい,の巻
2002/05/12 新規
JFileChooser クラス は、使いやすいファイル選択ダイアログを提供してくれます。 Java で GUI アプリの開発に携わったことがあるなら、大抵の人がその恩恵を受けたコトでしょう。
この選択ダイアログでファイルを選ぶとき、なにを対象とするかを事前に設定することができます。 その設定をすることで「ファイル」が対象なのか「ディレクトリ」なのか、もしくは両方かといった挙動が変わります。 「単一か複数か」という話は、今回は脇において置いてください。
とすれば、ファイルだけを選択できます。 このときディレクトリを選んで「開く」(または「保存」など)ボタンを押しても、 選択されたことにはならず、ダイアログも表示されたままの状態です。 挙動としては、そのディレクトリ直下に移動することになります。JFileChooser chooser=new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
ただし、1つだけ欠点があります。
それは「ファイル」だけを対象としても、ディレクトリを選んだときに、ファイル名を記述する欄にディレクトリ名が入ってしまいます。
つまり任意のファイル名を保持したまま、ディレクトリ移動することができないというコトになります。
これでは「ファイルのみ対象」という設定の有効性が、半減してしまっています。 今回の小技は、この挙動を修正することです。
基本的な理論は、こうです。 まずは JFileChooser クラス内部での挙動から。
さて。 理論がわかったところで、いざ実装をしてみようとすると、実はかなりの難問があることに気付きます。 API ドキュメント を見ても、また JFileChooser クラスのソースを見ても、どこにも「ファイル名記述欄に反映」している仕組みが見当たりません。 100% pure Java であると謳っているなら、そのソース・ファイルのどこかに記述があるはずです。 ・・・まぁ、配布されているソース一式には、省略されている部分も多いのですが。
ではドコにあるかと捜索してみると、けっこう深いところ、〜FileChooserUI クラスに隠されていました。
つまり、ファイル選択ダイアログの挙動を正すためには、自分なりのルック&フィールを用意しなければなりません。
修正する手法は説明も不要なほどに単純なのに、いざ実装するには遠回りをして面倒な手続きが必要です。
この面倒な手続き、独自のルック&フィール設定方法は自分だけのカッコ良いアプリを作りたい,の巻を参照してください。
後半部分は手抜きをしてますが、サンプル・ソースは参考になるはずです。
→ Musi_chanLookAndFeel.java
と言ったところで、あとは下のソース・コードを真似すれば、当初の目的を達することができます。
〜FileChooserUI クラスの setFileName() メソッドをどう変更するかで、ダイアログ内テキスト・フィールド(ファイル名記述欄)の挙動は自由自在。思いのままです。
import javax.swing.*; import javax.swing.plaf.*; import javax.swing.plaf.metal.*; import java.io.*; /** * Original look&feel (filechooser). * * @author Musi_chan * (Musi_chan@cool.biglobe.ne.jp) * @version 2002/05/10 18:09 */ public class Musi_chanFileChooserUI extends MetalFileChooserUI { public Musi_chanFileChooserUI(JFileChooser filechooser) { super(filechooser); } public static ComponentUI createUI(JComponent c) { return new Musi_chanFileChooserUI((JFileChooser) c); } public void setFileName(String filename) { String oldName; File file; oldName=getFileName(); file=getFileChooser().getSelectedFile(); if(file==null) { super.setFileName(oldName); return; } if(file.isDirectory()) { if(getFileChooser().isDirectorySelectionEnabled()) { super.setFileName(filename); } else { super.setFileName(oldName); } } else { if(getFileChooser().isFileSelectionEnabled()) { super.setFileName(filename); } else { super.setFileName(oldName); } } } } |