前回のエントリで指摘されたJTableを継承させる意味が無い問題を修正しJTableは継承せずに普通にnewした。あとはJTabbedPaneでタブを追加しフォルダをミドルクリックされたときに新規タブでファイル一覧を表示するようにした。
import java.awt.Color; import java.awt.Desktop; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.JOptionPane; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.filechooser.FileSystemView; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; import java.io.File; import java.io.IOException; public class JFiler{ public static void main(String... args){ SwingUtilities.invokeLater(JFiler::start); } private static void start(){ var frame = new JFrame(); var tab = new JTabbedPane(); var table = JFiler.createFileTable(tab, new File("./../")); table.setPreferredSize(new Dimension(600, 500)); tab.addTab(((FileModel)table.getModel()).getCurrentDirectoryName(), table); frame.add(tab); frame.setVisible(true); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private static JTable createFileTable(JTabbedPane tab, File dir){ var table = new JTable(); var model = new FileModel(); model.setCurrentDirectory(dir); table.setModel(model); table.getColumnModel().getColumn(0).setCellRenderer((t, value, isSelected, hasFocus, row, column) -> { var file = (File)value; var view = FileSystemView.getFileSystemView(); var icon = view.getSystemIcon(file); var label = new JLabel(file.getName(), icon, JLabel.LEFT); if(isSelected){ label.setOpaque(true); label.setBackground(new Color(0xCC, 0xCC, 0xFF)); } return label; }); table.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e){ var row = table.rowAtPoint(e.getPoint()); var column = table.columnAtPoint(e.getPoint()); table.changeSelection(row, column, false, false); if(SwingUtilities.isLeftMouseButton(e)){ JFiler.leftClicked(e, table, model); }else if(SwingUtilities.isMiddleMouseButton(e)){ var file = (File)model.getValueAt(table.getSelectedRow(), 0); if(file.isDirectory()){ var newTable = JFiler.createFileTable(tab, file); tab.addTab(((FileModel)newTable.getModel()).getCurrentDirectoryName(), newTable); tab.setSelectedComponent(newTable); } } } }); return table; } private static void leftClicked(MouseEvent e, JTable table, FileModel model){ if(e.getClickCount() == 2){ var file = (File)model.getValueAt(table.getSelectedRow(), 0); if(file.isDirectory()){ model.setCurrentDirectory(file); table.repaint(); }else{ try{ Desktop.getDesktop().open(file); }catch(IOException exception){ JOptionPane.showConfirmDialog(table, exception.getMessage()); } } } } private static class FileModel extends AbstractTableModel{ private File dir; private File[] children; public String getCurrentDirectoryName(){ try{ var path = dir.getCanonicalPath(); var index = path.lastIndexOf(File.separator); return path.substring(index + 1, path.length()); }catch(IOException e){ return dir.getName(); } } public void setCurrentDirectory(File dir){ this.dir = dir; this.children = dir.listFiles(); } public int getRowCount(){ return children.length; } public int getColumnCount(){ return 1; } public Object getValueAt(int row, int column){ return children[row]; } } }