「Java/swing/サンプル/JTreeとJListで作るエクスプローラ風のサンプル」の編集履歴(バックアップ)一覧はこちら

Java/swing/サンプル/JTreeとJListで作るエクスプローラ風のサンプル」(2012/10/07 (日) 16:31:37) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

&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には入ってなかったりするのかな?

表示オプション

横に並べて表示:
変化行の前後のみ表示: