DirectoryChooser

 Windowsでよく見かける、DirectoryChooserを書いてみる。

ソースコード

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

public class DirectoryChooser extends JDialog {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTree tree;
	private JTextField text;
	private File selectedFile;
	private String sep=System.getProperty("file.separator");
	private JScrollPane scroll;
	
	public DirectoryChooser(Frame f,boolean modal){
		super(f,modal);
		super.getContentPane().setLayout(new BorderLayout());
		super.setTitle("Select Dir");
		tree=new JTree();
		tree.setRowHeight(20);
		tree.addMouseListener(new MouseAction());
		DefaultMutableTreeNode root=new DefaultMutableTreeNode("root");
		File[] ff=File.listRoots();
		for(File dir :ff){
			DirectoryTreeNode dn=new DirectoryTreeNode(dir);
			dn.setUserObject(dir.getAbsoluteFile());
			root.add(dn);
		}
		DefaultTreeModel model=new DefaultTreeModel(root);
		tree.setModel(model);
		scroll=new JScrollPane(tree);
		super.getContentPane().add(scroll,BorderLayout.CENTER);
		JPanel under=new JPanel(new GridLayout(2,1));
		super.getContentPane().add(under,BorderLayout.SOUTH);
		JPanel uu=new JPanel(new BorderLayout());
		text=new JTextField();
		text.setEditable(false);
		Font font=new Font(Font.SANS_SERIF,Font.PLAIN,12);
		text.setFont(font);
		text.setBackground(Color.WHITE);
		text.setBorder(BorderFactory.createLoweredBevelBorder());
		JLabel ll=new JLabel("Path");
		ll.setHorizontalAlignment(JLabel.CENTER);
		ll.setFont(font);
		ll.setPreferredSize(new Dimension(40,24));
		uu.add(ll,BorderLayout.WEST);
		uu.add(text,BorderLayout.CENTER);
		under.add(uu);
		JPanel tool=new JPanel();
		BoxLayout bl=new BoxLayout(tool,BoxLayout.X_AXIS);
		tool.setLayout(bl);
		JButton bt0=new JButton("Create Dir");
		bt0.setFont(font);
		bt0.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(selectedFile==null)return;
				String name=JOptionPane.showInputDialog(
						tree, "Input the name of a new directory.");
				if(name==null||name.isEmpty())return;
				String path=selectedFile.getAbsolutePath()+sep+name;
				File ff=new File(path);
				if(ff.exists()){
					JOptionPane.showMessageDialog(
							tree, "The directory exists. ","",
							JOptionPane.WARNING_MESSAGE);
					return;
				}
				if(ff.mkdir()){
					DefaultTreeModel mm=(DefaultTreeModel)tree.getModel();
					DirectoryTreeNode dn=new DirectoryTreeNode(ff);
					TreePath tp=tree.getSelectionPath();
					DirectoryTreeNode pn=
						(DirectoryTreeNode)tp.getLastPathComponent();
					mm.insertNodeInto(dn, pn, pn.getChildCount());
					selectedFile=ff;
					final TreePath tx=new TreePath(mm.getPathToRoot(dn));
					Runnable r=new Runnable(){
						public void run(){
							text.setText(selectedFile.getAbsolutePath());
							tree.setSelectionPath(tx);
							tree.expandPath(tx);
						}
					};
					javax.swing.SwingUtilities.invokeLater(r);
				}else{
					JOptionPane.showMessageDialog(
							tree, "It failed in making the directory. ","",
							JOptionPane.WARNING_MESSAGE);
				}
			}
		});
		tool.add(bt0);
		tool.add(Box.createGlue());
		JButton bt1=new JButton("OK");
		bt1.setFont(font);
		bt1.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				setVisible(false);
			}
		});
		bt1.setPreferredSize(new Dimension(70,24));
		JButton bt2=new JButton("Cancel");
		bt2.setFont(font);
		bt2.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				selectedFile=null;
				setVisible(false);
			}
		});
		bt2.setPreferredSize(new Dimension(70,24));
		tool.add(bt1);
		tool.add(bt2);
		under.add(tool);
		pack();
	}
	
	public File getSelectedDir(){
		return selectedFile;
	}
	
	public static File showDirectryChooser(Component c){
		DirectoryChooser dc=new DirectoryChooser(
				JOptionPane.getFrameForComponent(c),true);
		dc.setLocationRelativeTo(c);
		dc.setSize(400, 400);
		dc.setLocationRelativeTo(null);
		dc.setVisible(true);
		return dc.selectedFile;
	}
	
	private void scanChildren(DefaultTreeModel model,DirectoryTreeNode n){
		if(n.isScan)return;
		File[] fs=n.file.listFiles();
		if(fs==null)return;
		for(File ff : fs){
			if(ff.isDirectory()){
				model.insertNodeInto(new DirectoryTreeNode(ff),
						n, n.getChildCount());
			}
		}
		n.isScan=true;
	}
	
	private class DirectoryTreeNode extends DefaultMutableTreeNode{
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private File file;
		private boolean isScan=false;
		
		public DirectoryTreeNode(File f){
			super(f.getName());
			file=f;
		}

		@Override
		public boolean isLeaf() {
			return false;
		}
	}
	
	private class MouseAction extends MouseAdapter{
		@Override
		public void mouseClicked(MouseEvent arg0) {
			JTree t=(JTree)arg0.getSource();
			TreePath tp=t.getSelectionPath();
			if(tp==null)return;
			Object o=tp.getLastPathComponent();
			if(o instanceof DirectoryTreeNode){
				DefaultTreeModel dt=(DefaultTreeModel)t.getModel();
				DirectoryTreeNode dn=(DirectoryTreeNode)o;
				scanChildren(dt,dn);
				selectedFile=dn.file;
				text.setText(selectedFile.getAbsolutePath());
			}else{
				selectedFile=null;
				text.setText("");
			}
		}
	}
	
	public static void main(String[] args){
		JFrame frame=new JFrame();
		try {
			UIManager.setLookAndFeel(
					"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
			SwingUtilities.updateComponentTreeUI(frame);
		}catch(Exception e){
			try {
				UIManager.setLookAndFeel(
						"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
				SwingUtilities.updateComponentTreeUI(frame);
			}catch(Exception ee){
				ee.printStackTrace();
			}	
		}
		File f=DirectoryChooser.showDirectryChooser(frame);
		if(f!=null)System.out.println(f.getAbsolutePath());
		System.exit(0);
	}
}

■実行結果
 こんな感じになります。