「Java/swing/サンプル/JTreeとJListで作るエクスプローラ風のサンプル」の編集履歴(バックアップ)一覧はこちら
追加された行は緑色になります。
削除された行は赤色になります。
&ref(swingエクスプローラ風サンプル.png)
*** 解説
- JTreeとJListで作るエクスプローラ風のサンプル-
-- JTreeにディレクトリ構造を表示
-- JListにJTreeで選択したディレクトリの内容を表示
-- JListのディレクトリをダブルクリック、エンターでディレクトリの中を表示
-- JListのファイルをダブルクリック、エンターで関連付け実行
参考
FileSystemViewを使ってディレクトリ構造をJTreeに表示する - Java Swing Tips
http://terai.xrea.jp/Swing/DirectoryTree.html
参考というかJTreeの部分はちょこちょこ改造したけど、殆どそのままJListを追加した形です
*** ソース &ref(ExplorerLikeSample.java)
#highlight(java){{
/*
* JTreeとJListで作るエクスプローラ風のサンプル
* ・JTreeにディレクトリ構造を表示
* ・JListにJTreeで選択したディレクトリの内容を表示
* ・JListのディレクトリをダブルクリック、エンターでディレクトリの中を表示
* ・JListのファイルをダブルクリック、エンターで関連付け実行
* 参考
* FileSystemViewを使ってディレクトリ構造をJTreeに表示する - Java Swing Tips
* http://terai.xrea.jp/Swing/DirectoryTree.html
* 参考というかJTreeの部分はちょこちょこ改造したけど、殆どそのままJListを追加した形です
*/
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import sun.awt.shell.ShellFolder;
public class ExplorerLikeSample extends JPanel {
DefaultListModel listModel;
DefaultTreeModel treeModel;
JTree tree;
JList jList;
public ExplorerLikeSample() {
super(new BorderLayout());
FileSystemView fileSystemView = FileSystemView.getFileSystemView();
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
treeModel = new DefaultTreeModel(root);
for (File fileSystemRoot : fileSystemView.getRoots()) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(
fileSystemRoot);
root.add(node);
for (File file : fileSystemView.getFiles(fileSystemRoot, true)) {
if (file.isDirectory()) {
node.add(new DefaultMutableTreeNode(file));
}
}
}
// 初期化の追加部分
tree = new JTree(treeModel);
tree.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
tree.setRootVisible(false);
tree.addTreeSelectionListener(new FolderSelectionListener(
fileSystemView));
tree.setCellRenderer(new FileTreeCellRenderer(tree.getCellRenderer(),
fileSystemView));
tree.expandRow(0);
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
sp.setDividerSize(1);
sp.add(new JScrollPane(tree), 0);
listModel = new DefaultListModel();
JList list = new JList(listModel);
list.setFixedCellHeight(84);
list.setFixedCellWidth(84);
list.setCellRenderer(new FileListCellRenderer(fileSystemView));
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(0);
list.addMouseListener(new ListMouseListener());
list.addKeyListener(new ListKeyListener());
jList = list;
sp.add(new JScrollPane(list), 1);
add(sp);
// 初期化の追加部分ここまで
setPreferredSize(new Dimension(400, 240));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
JFrame frame = new JFrame("Swingエクスプローラ風サンプル(JTree, JList)");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new ExplorerLikeSample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class FolderSelectionListener implements TreeSelectionListener {
private final FileSystemView fileSystemView;
public FolderSelectionListener(FileSystemView fileSystemView) {
this.fileSystemView = fileSystemView;
}
@Override
public void valueChanged(TreeSelectionEvent e) {
JTree tree = (JTree) e.getSource();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getPath()
.getLastPathComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
File parent = (File) node.getUserObject();
if (!parent.isDirectory())
return;
SwingWorker<String, File> worker = new SwingWorker<String, File>() {
File parent;
DefaultMutableTreeNode node;
DefaultTreeModel model;
SwingWorker<String, File> setParam(File parent,
DefaultMutableTreeNode node, DefaultTreeModel model) {
this.parent = parent;
this.node = node;
this.model = model;
return this;
}
@Override
public String doInBackground() {
File[] children = fileSystemView.getFiles(parent, true);
publish(children);
return "done";
}
@Override
protected void process(List<File> children) {
HashMap<File, File> map = new HashMap<File, File>();
listModel.removeAllElements();
boolean isLeaf = node.isLeaf();
if (!isLeaf) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) node
.getFirstChild();
while (n != null) {
File f = (File) n.getUserObject();
map.put(f, f);
n = n.getNextNode();
}
}
for (File child : children) {
if (child.isDirectory()) {
if (isLeaf) {
node.add(new DefaultMutableTreeNode(child));
} else {
if (!map.containsKey(child)) {
node.add(new DefaultMutableTreeNode(child));
}
}
}
// list更新
listModel.addElement(child);
}
model.nodeStructureChanged(node);
}
}.setParam(parent, node, model);
worker.execute();
}
}
class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private final TreeCellRenderer renderer;
private final FileSystemView fileSystemView;
public FileTreeCellRenderer(TreeCellRenderer renderer,
FileSystemView fileSystemView) {
this.renderer = renderer;
this.fileSystemView = fileSystemView;
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
JLabel c = (JLabel) renderer.getTreeCellRendererComponent(tree,
value, isSelected, expanded, leaf, row, hasFocus);
if (isSelected) {
c.setOpaque(false);
c.setForeground(getTextSelectionColor());
} else {
c.setOpaque(true);
c.setForeground(getTextNonSelectionColor());
c.setBackground(getBackgroundNonSelectionColor());
}
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Object o = node.getUserObject();
if (o instanceof File) {
File file = (File) o;
c.setIcon(fileSystemView.getSystemIcon(file));
c.setText(fileSystemView.getSystemDisplayName(file));
c.setToolTipText(file.getPath());
}
}
return c;
}
}
// 以降が追加部分
/**
* JList用のキーリスナー
*/
class ListKeyListener extends KeyAdapter {
@Override
public void keyTyped(KeyEvent e) {
super.keyTyped(e);
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
listAction();
}
}
}
/**
* JList用のマウスリスナー
*/
class ListMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
listAction(e.getPoint());
}
}
}
/**
* JListの選択アイテムのアクション
*/
void listAction() {
listAction(jList.getSelectedIndex());
}
/**
* JListの指定座標のアクション
*/
void listAction(Point point) {
// カーソル下のアイテム選択
int index = jList.locationToIndex(point);
if (!jList.getCellBounds(index, index).contains(point)) {
index = -1;
}
if (index >= 0) {
listAction(index);
}
}
/**
* JList用の指定インデックスのアクション
*/
private void listAction(int index) {
File f = (File) listModel.get(index);
if (f.isDirectory()) {
listActionDirectry(f);
} else {
listActionFile(f);
}
}
/**
* JList用のファイルアクション
*/
private void listActionFile(File f) {
if (!Desktop.isDesktopSupported()) {
return;
}
try {
Desktop.getDesktop().open(f);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* JList用のディレクトリアクション
*/
private void listActionDirectry(File f) {
TreePath path = tree.getSelectionPath();
DefaultMutableTreeNode n = (DefaultMutableTreeNode) path
.getLastPathComponent();
File tf = (File) n.getUserObject();
File pf = f.getParentFile();
if (tf.equals(pf)) {
for (int i = 0; i < n.getChildCount(); i++) {
DefaultMutableTreeNode c = (DefaultMutableTreeNode) n
.getChildAt(i);
File cf = (File) c.getUserObject();
if (cf.equals(f)) {
TreePath newPath = path.pathByAddingChild(c);
tree.setSelectionPath(newPath);
}
}
}
}
/**
* JList用のセルセンダラー
*/
class FileListCellRenderer extends DefaultListCellRenderer {
FileSystemView fs = FileSystemView.getFileSystemView();
public FileListCellRenderer(FileSystemView fileSystemView) {
this.fs = fileSystemView;
// テキストを下に表示する
setVerticalTextPosition(BOTTOM);
// テキスト中央揃え
setHorizontalTextPosition(CENTER);
// アイコン中央揃え
setVerticalAlignment(CENTER);
setHorizontalAlignment(CENTER);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
if (value instanceof File) {
File f = (File) value;
setText(fs.getSystemDisplayName(f));
Icon icon = null;
try {
Image img = ShellFolder.getShellFolder(f).getIcon(true);
if (img != null) {
icon = new ImageIcon(img);
} else {
icon = UIManager
.getIcon(f.isDirectory() ? "FileView.directoryIcon"
: "FileView.fileIcon");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
setIcon(icon);
}
return this;
}
}
}
}}
*** ShellFolderのエラー
&ref(swingShellFolderのエラー.png)
eclipseから見ると赤いマークが出ててイラッとしますが、このままで実行できました。不思議
参考
FileのSystemIconを取得する - Java Swing Tips
http://terai.xrea.jp/Swing/SystemIcon.html
今後のリリースで削除される可能性がある?もしかしたらOpenJDKには入ってなかったりするのかな?
&ref(swingエクスプローラ風サンプル.png)
*** 解説
- JTreeとJListで作るエクスプローラ風のサンプル-
-- JTreeにディレクトリ構造を表示
-- JListにJTreeで選択したディレクトリの内容を表示
-- JListのディレクトリをダブルクリック、エンターでディレクトリの中を表示
-- JListのファイルをダブルクリック、エンターで関連付け実行
参考
FileSystemViewを使ってディレクトリ構造をJTreeに表示する - Java Swing Tips
http://terai.xrea.jp/Swing/DirectoryTree.html
参考というかJTreeの部分はちょこちょこ改造したけど、殆どそのままJListを追加した形です
*** ソース &ref(ExplorerLikeSample.java)
#highlight(java){{
/*
* JTreeとJListで作るエクスプローラ風のサンプル
* ・JTreeにディレクトリ構造を表示
* ・JListにJTreeで選択したディレクトリの内容を表示
* ・JListのディレクトリをダブルクリック、エンターでディレクトリの中を表示
* ・JListのファイルをダブルクリック、エンターで関連付け実行
* 参考
* FileSystemViewを使ってディレクトリ構造をJTreeに表示する - Java Swing Tips
* http://terai.xrea.jp/Swing/DirectoryTree.html
* 参考というかJTreeの部分はちょこちょこ改造したけど、殆どそのままJListを追加した形です
*/
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import sun.awt.shell.ShellFolder;
public class ExplorerLikeSample extends JPanel {
DefaultListModel listModel;
DefaultTreeModel treeModel;
JTree tree;
JList jList;
public ExplorerLikeSample() {
super(new BorderLayout());
FileSystemView fileSystemView = FileSystemView.getFileSystemView();
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
treeModel = new DefaultTreeModel(root);
for (File fileSystemRoot : fileSystemView.getRoots()) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(
fileSystemRoot);
root.add(node);
for (File file : fileSystemView.getFiles(fileSystemRoot, true)) {
if (file.isDirectory()) {
node.add(new DefaultMutableTreeNode(file));
}
}
}
// 初期化の追加部分
tree = new JTree(treeModel);
tree.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
tree.setRootVisible(false);
tree.addTreeSelectionListener(new FolderSelectionListener(
fileSystemView));
tree.setCellRenderer(new FileTreeCellRenderer(tree.getCellRenderer(),
fileSystemView));
tree.expandRow(0);
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
sp.setDividerSize(1);
sp.add(new JScrollPane(tree), 0);
listModel = new DefaultListModel();
JList list = new JList(listModel);
list.setFixedCellHeight(84);
list.setFixedCellWidth(84);
list.setCellRenderer(new FileListCellRenderer(fileSystemView));
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(0);
list.addMouseListener(new ListMouseListener());
list.addKeyListener(new ListKeyListener());
jList = list;
sp.add(new JScrollPane(list), 1);
add(sp);
// 初期化の追加部分ここまで
setPreferredSize(new Dimension(400, 240));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
JFrame frame = new JFrame("Swingエクスプローラ風サンプル(JTree, JList)");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new ExplorerLikeSample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class FolderSelectionListener implements TreeSelectionListener {
private final FileSystemView fileSystemView;
public FolderSelectionListener(FileSystemView fileSystemView) {
this.fileSystemView = fileSystemView;
}
@Override
public void valueChanged(TreeSelectionEvent e) {
JTree tree = (JTree) e.getSource();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getPath()
.getLastPathComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
File parent = (File) node.getUserObject();
if (parent == null || !parent.isDirectory())
return;
SwingWorker<String, File> worker = new SwingWorker<String, File>() {
File parent;
DefaultMutableTreeNode node;
DefaultTreeModel model;
SwingWorker<String, File> setParam(File parent,
DefaultMutableTreeNode node, DefaultTreeModel model) {
this.parent = parent;
this.node = node;
this.model = model;
return this;
}
@Override
public String doInBackground() {
File[] children = fileSystemView.getFiles(parent, true);
publish(children);
return "done";
}
@Override
protected void process(List<File> children) {
HashMap<File, File> map = new HashMap<File, File>();
listModel.removeAllElements();
boolean isLeaf = node.isLeaf();
if (!isLeaf) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) node
.getFirstChild();
while (n != null) {
File f = (File) n.getUserObject();
map.put(f, f);
n = n.getNextNode();
}
}
for (File child : children) {
if (child.isDirectory()) {
if (isLeaf) {
node.add(new DefaultMutableTreeNode(child));
} else {
if (!map.containsKey(child)) {
node.add(new DefaultMutableTreeNode(child));
}
}
}
// list更新
listModel.addElement(child);
}
model.nodeStructureChanged(node);
}
}.setParam(parent, node, model);
worker.execute();
}
}
class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private final TreeCellRenderer renderer;
private final FileSystemView fileSystemView;
public FileTreeCellRenderer(TreeCellRenderer renderer,
FileSystemView fileSystemView) {
this.renderer = renderer;
this.fileSystemView = fileSystemView;
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
JLabel c = (JLabel) renderer.getTreeCellRendererComponent(tree,
value, isSelected, expanded, leaf, row, hasFocus);
if (isSelected) {
c.setOpaque(false);
c.setForeground(getTextSelectionColor());
} else {
c.setOpaque(true);
c.setForeground(getTextNonSelectionColor());
c.setBackground(getBackgroundNonSelectionColor());
}
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Object o = node.getUserObject();
if (o instanceof File) {
File file = (File) o;
c.setIcon(fileSystemView.getSystemIcon(file));
c.setText(fileSystemView.getSystemDisplayName(file));
c.setToolTipText(file.getPath());
}
}
return c;
}
}
// 以降が追加部分
/**
* JList用のキーリスナー
*/
class ListKeyListener extends KeyAdapter {
@Override
public void keyReleased(KeyEvent e) {
super.keyTyped(e);
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
listAction();
} else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
listBack();
}
}
}
/**
* JList用のマウスリスナー
*/
class ListMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
listAction(e.getPoint());
}
}
}
/**
* JListの選択アイテムのアクション
*/
void listAction() {
listAction(jList.getSelectedIndex());
}
/**
* JListの指定座標のアクション
*/
void listAction(Point point) {
// カーソル下のアイテム選択
int index = jList.locationToIndex(point);
if (!jList.getCellBounds(index, index).contains(point)) {
index = -1;
}
if (index >= 0) {
listAction(index);
}
}
/**
* JList用の指定インデックスのアクション
*/
private void listAction(int index) {
File f = (File) listModel.get(index);
if (f.isDirectory()) {
listActionDirectry(f);
} else {
listActionFile(f);
}
}
/**
* JList用のファイルアクション
*/
private void listActionFile(File f) {
if (!Desktop.isDesktopSupported()) {
return;
}
try {
Desktop.getDesktop().open(f);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* JList用のディレクトリアクション
*/
private void listActionDirectry(File f) {
TreePath path = tree.getSelectionPath();
DefaultMutableTreeNode n = (DefaultMutableTreeNode) path
.getLastPathComponent();
File tf = (File) n.getUserObject();
File pf = f.getParentFile();
if (tf.equals(pf)) {
for (int i = 0; i < n.getChildCount(); i++) {
DefaultMutableTreeNode c = (DefaultMutableTreeNode) n
.getChildAt(i);
File cf = (File) c.getUserObject();
if (cf.equals(f)) {
TreePath newPath = path.pathByAddingChild(c);
tree.setSelectionPath(newPath);
}
}
}
}
/**
* 戻るアクション
*/
private void listBack() {
TreePath path = tree.getSelectionPath().getParentPath();
if (path != null && path.getPathCount() != 0) {
tree.setSelectionPath(path);
}
}
/**
* JList用のセルセンダラー
*/
class FileListCellRenderer extends DefaultListCellRenderer {
FileSystemView fs = FileSystemView.getFileSystemView();
public FileListCellRenderer(FileSystemView fileSystemView) {
this.fs = fileSystemView;
// テキストを下に表示する
setVerticalTextPosition(BOTTOM);
// テキスト中央揃え
setHorizontalTextPosition(CENTER);
// アイコン中央揃え
setVerticalAlignment(CENTER);
setHorizontalAlignment(CENTER);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
if (value instanceof File) {
File f = (File) value;
setText(fs.getSystemDisplayName(f));
Icon icon = null;
try {
Image img = ShellFolder.getShellFolder(f).getIcon(true);
if (img != null) {
icon = new ImageIcon(img);
} else {
icon = UIManager
.getIcon(f.isDirectory() ? "FileView.directoryIcon"
: "FileView.fileIcon");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
setIcon(icon);
}
return this;
}
}
}
}}
*** ShellFolderのエラー
&ref(swingShellFolderのエラー.png)
eclipseから見ると赤いマークが出ててイラッとしますが、このままで実行できました。不思議
参考
FileのSystemIconを取得する - Java Swing Tips
http://terai.xrea.jp/Swing/SystemIcon.html
今後のリリースで削除される可能性がある?もしかしたらOpenJDKには入ってなかったりするのかな?