ファイルチューザ


ファイル選択ダイアログ

AWT では、ファイルを選択するなどの便利なダイアログは存在しませんでした
しかし、Swing ではチューザと呼ばれる標準的な選択ダイアログがサポートされています
それも多くの場合、従来のプラットフォームが提供する機能に比べ、柔軟で強力でしょう

ファイルを選択する標準ダイアログはファイルチューザと呼ばれています
これは javax.swing.JFileChooser クラスを用います
java.lang.Object
  |
  +--java.awt.Component
        |
        +--java.awt.Container
              |
              +--javax.swing.JComponent
                    |
                    +--javax.swing.JFileChooser

public class JFileChooser
	extends JComponent implements Accessible
このクラスには、次のようなコンストラクタがあります

public JFileChooser()
public JFileChooser(String currentDirectoryPath)
public JFileChooser(File currentDirectory)
public JFileChooser(FileSystemView fsv)
public JFileChooser(File currentDirectory , FileSystemView fsv)
public JFileChooser(String currentDirectoryPath , FileSystemView fsv)

currentDirectoryPath はファイルまたはディレクトリのパスを指定します
currentDirectory も同様で、パスを示す File オブジェクトを指定します
チューザはこのパスを参考に、デフォルトディレクトリを決定して構築されます

fsv は、システム固有のファイル情報を把握するための FileSystemView を指定します
この場では、この機能については省略します

ファイルを開くには JFileChooser.showOpenDialog() メソッドを
保存するには JFileChooser.showSaveDialog() メソッドを使います
これらは、基本的にボタンのテキストが違うだけで基本機能は同じです
独自のファイルチューザを JFileChooser.showDialog() で作ることもできます
public int showOpenDialog(
	Component parent
) throws HeadlessException
public int showSaveDialog(
	Component parent
) throws HeadlessException
public int showDialog(
	Component parent , String approveButtonText
) throws HeadlessException
parent には親コンポーネントを指定します
approveButtonText は、ファイルチューザの承認ボタンのテキストを指定します

ユーザーが承認ボタンを押してファイルを選択したのであれば
その後 JFileChooser.getSelectedFile() メソッドでファイルを取得できます
ファイルをプログラムから選択するための JFileChooser.setSlectedFile() もあります

public void setSelectedFile(File file)
public File getSelectedFile()

file には選択するファイルを指定します
ファイルが設定されていない場合、getSlectedFile() は null を返します
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test {
	public static void main(String args[]) {
		JFrame frame = new JFrame("Kitty on your lap");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent e) {
				System.exit(0);
			}
		});

		JFileChooser file = new JFileChooser();
		if (file.showOpenDialog(frame) == JFileChooser.CANCEL_OPTION)
			System.exit(0);

		Icon icon = new ImageIcon(file.getSelectedFile().getPath());
		frame.getContentPane().add(new JScrollPane(new JLabel(icon)));

		frame.setSize(400 , 400);
		frame.setVisible(true);
	}
}


このプログラムは、ファイルチューザを表示して画像ファイルを選択します
画像ファイルを選択して「開く」ボタンを押せば
ウィンドウフレームに画像を含むスクロールペインが表示されます

ファイルチューザには、アクセサリと呼ばれる機能を追加することができます
アクセサリは JComponent を継承する軽量コンポーネントです
どのように使われても良いのですが、一般的にはファイルプレビューに利用します

アクセサリは JFileChooser.setAccessory() メソッドで設定し
JFileChooser.getAccessory() メソッドで取得することができます

public void setAccessory(JComponent newAccessory)
public JComponent getAccessory()

newAccessory には新しいアクセサリコンポーネントを指定します
チューザは、基本的に幅のレイアウトはアクセサリの推奨幅を尊重します
必要に応じて、アクセサリコンポーネントの推奨サイズを変更してください
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;

public class Test extends JFrame implements PropertyChangeListener {
	public static void main(String args[]) {
		JFrame frame = new Test();
		frame.setSize(400 , 400);
		frame.setVisible(true);
	}

	JLabel label = new JLabel();
	JFileChooser fcsr = new JFileChooser();
	public Test() {
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent e) {
				System.exit(0);
			}
		});

		JScrollPane scroll = new JScrollPane(label);
		scroll.setPreferredSize(new Dimension(200 , 0));
		fcsr.setAccessory(scroll);
		fcsr.addPropertyChangeListener(this);

		fcsr.showOpenDialog(this);
	}

	public void propertyChange(PropertyChangeEvent e) {
		java.io.File file = fcsr.getSelectedFile();
		if (file == null) return;
		label.setIcon(new ImageIcon(file.getPath()));
	}
}


このプログラムは、画像ファイルが選択された時
アクセサリコンポーネントが、画像ファイルのプレビュを表示します
選択の監視は addPropertyChangeListener() をチューザに追加することで行っています

ファイル選択時に、何らかの条件を満たしたファイルのみを表示できると便利です
例えば、ファイルサイズが 1MB 以上とか、拡張子が txt のファイルを表示するなどです
なぜならば、ファイルの保存や展開は、多くの場合対象が決められているからです

こうした機能を追加するには javax.swing.filechooser.FileFilter クラスを使います
このクラスは、ファイルフィルタの条件とその説明文を定義するための抽象クラスです

public abstract class FileFilter extends Object

このクラスは、二つのメソッドを宣言しています
FileFilter.accept() はファイルを表示するかどうかを返し
FileFilter.getDescription() は、フィルタ説明文を返します

public abstract boolean accept(File f)
public abstract String getDescription()

f には、フィルタをチェックするファイルを指定します
accept() は、このファイルが表示条件を満たしている場合 true を返します
getDescription() は、フィルタの意味を説明するための String を返します

フィルタは JFileChooser.addChoosableFileFilter() で追加できます
フィルタを解除するには JFileChooser.removeChoosableFileFilter()
全て解除するには JFileChooser.resetChoosableFileFilters() を使います

public void addChoosableFileFilter(FileFilter filter)
public boolean removeChoosableFileFilter(FileFilter f)
public void resetChoosableFileFilters()

filter には追加するファイルフィルタを
f には解除するファイルフィルタを指定します
removeChoosableFileFilter() は、解除が成功すれば true を返します
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JFrame {
	public static void main(String args[]) {
		JFrame frame = new Test();
	}

	JFileChooser fcsr = new JFileChooser();
	public Test() {
		FileFilterEx filter[] = {
			new FileFilterEx(".jpg" , "JPEG ファイル(*.jpg)") ,
			new FileFilterEx(".gif" , "GIF ファイル(*.gif)") ,
			new FileFilterEx(".txt" , "テキストファイル(*.txt)")
		};
		for(int i = 0 ; i < filter.length ; i++)
			fcsr.addChoosableFileFilter(filter[i]);
		fcsr.showOpenDialog(this);
		System.exit(0);
	}
}

class FileFilterEx extends javax.swing.filechooser.FileFilter {
	private String extension , msg;
	public FileFilterEx(String extension , String msg) {
		this.extension = extension;
		this.msg = msg;
	}
	public boolean accept(java.io.File f) {
		return f.getName().endsWith(extension);
	}
	public String getDescription() { return msg; }
}


このプログラムは、拡張子でフィルタリングを行う FileFilterEx クラスを作成し
これに、表示させたい拡張子と説明文を指定してインスタンスを作成しています
作成した FileFilterEx をファイルチューザに設定しています
その結果、「ファイルタイプ」コンボボックスに反映されていることが確認できます

デフォルトでファイルチューザは単一のファイルしか選択できませんが
複数のファイルを選択させたい場合もあるでしょう
この場合は JFileChooser.setMultiSelectionEnabled() を使います
この値は JFileChooser.isMultiSelectionEnabled() で得ることができます

public void setMultiSelectionEnabled(boolean b)
public boolean isMultiSelectionEnabled()

b には、複数選択を可能にするかどうかを表すブーリアンを指定します
ここに true を指定すれば、チューザは複数選択をサポートするようになります
複数選択は JFileChooser.getSelectedFiles() で取得できます
また JFileChooser.setSelectedFiles() で設定することもできます

public void setSelectedFiles(File[] selectedFiles)
public File[] getSelectedFiles()

selectedFiles には複数選択のファイルを指定します
import java.awt.*;
import javax.swing.*;

public class Test extends JFrame {
	public static void main(String args[]) {
		JFrame frame = new Test();
	}

	JFileChooser fcsr = new JFileChooser();
	public Test() {
		fcsr.setMultiSelectionEnabled(true);
		fcsr.showOpenDialog(this);
		JOptionPane.showMessageDialog(this , fcsr.getSelectedFiles());

		System.exit(0);
	}
}


このプログラムのファイルチューザは、複数のファイルを選択することができます
選択後、選択したファイルをメッセージダイアログで表示します

ところで、Swing のファイルチューザはデフォルトでファイルのアイコンを用意していますが
すべてのファイルのアイコンが、単純なファイルアイコンで表示されています
高度なソフトウェアの開発には、アイコンをより分かりやすく
ファイルの種類などに応じて区別できるように工夫するべきだと考えられます

ファイルチューザは、ファイルを表示する前にファイルビューを呼び出します
ファイルビューは、与えられた情報を元に、どのようにファイルを表示するか
アイコンやファイル名をファイルチューザに返すという仕組みになっているのです

ファイルビューは javax.swing.filechooser.FileView を使います
これは、チューザが呼び出すファイルビューの抽象クラスです

public abstract class FileView extends Object

このクラスは、チューザが必要とする基本的な情報を提供します
ファイル名は FileView.getName() メソッドで取得し
ファイルそのものの説明は FileView.getDescription() で返せます
ファイルタイプの説明は FileView.getTypeDescription() メソッドが
ファイルのアイコンは FileView.getIcon() メソッドが返します

ファイルがディレクトリの場合 FileView.isTraversable() が重要になります
これは、ファイルを展開できる場合は true、そうでなければ false を返します
デフォルトではディレクトリに対して true を返すように設定されていますが
ディレクトリに対して false を返せば、ディレクトリを選択させることができるようになります

public String getName(File f)
public String getDescription(File f)
public String getTypeDescription(File f)
public Icon getIcon(File f)
public Boolean isTraversable(File f)

f は、ファイルビューに表示方法を問い合わせるファイルを指定します
ファイルチューザは、これらのメソッドを呼び出してファイルの情報を取得し
その情報を元に、ファイルのアイコンや名前を表示します

開発者は FileView クラスをサブクラス化し、これをチューザに設定できます
デフォルトの機能を使いたい場合は、それぞれの機能に対して null を返します
ファイルビューの登録には JFileChooser.setFileView() を用います
JFileChooser.getFileView() メソッドでファイルビューを取得することもできます

public void setFileView(FileView fileView)
public FileView getFileView()

fileView には、新たに設定するファイルビューを指定します
import java.awt.*;
import java.io.*;
import javax.swing.*;

public class Test extends JFrame {
	public static void main(String args[]) {
		JFrame frame = new Test();
	}

	JFileChooser fcsr = new JFileChooser();
	public Test() {
		fcsr.setFileView(new IconFileView(".wis" , new ImageIcon("icon.jpg")));
		fcsr.showOpenDialog(this);
		System.exit(0);
	}
}

class IconFileView extends javax.swing.filechooser.FileView {
	String extension;
	Icon icon;

	public IconFileView(String extension , Icon icon) {
		this.extension = extension;
		this.icon = icon;
	}
	public Icon getIcon(File f) {
		if (f.getName().endsWith(extension)) return icon;
		else return null;
	}
}


このプログラムでは FileView をサブクラス化した
アイコンと拡張子のビューを拡張する IconFileView クラスを作成しています
これに、拡張子とアイコンを関連付け、それをファイルチューザに設定しています
その結果 .wis という拡張子に対して、指定したアイコンが表示されるようになりました



前のページへ戻る次のページへ