java实现Windows资源管理器(JExplorer)

程序仅仅实现了仿Windows资源管理器的本地文件的浏览功能,不能通过“网上邻居”浏览邻近的电脑,另外,“控制面板”和“垃圾箱”也没能列出来。
程序包括3个文件,分别是JExplorer.java、FileTree.java和FileList.java。可以在网页中tl.exercise.swing文件夹中找到。其中FileTree.java中定义了一个用来显示Windows文件夹的树;顾名思义FileList.java中定义的是列表,不够这个列表很简单;main函数在JExplorer.java里面。

树的实现其实很简单,主要使用了两个技术:
1. 使用javax.swing.filechooser.FileSystemView列举系统文件夹,获得系统图标。
2. 使用javax.swing.tree.DefaultTreeCellRenderer改变Node的图标。
===================================================================

// FileTree.java
/***********************************************************

* Author: Jason

* email: tl21cen@hotmail.com

* CSDN blog: http://blog.csdn.net/UnAgain/

***********************************************************/

package tl.exercise.swing;



import java.awt.Component;

import java.io.File;

import java.util.Vector;



import javax.swing.Icon;

import javax.swing.JTree;

import javax.swing.event.TreeExpansionEvent;

import javax.swing.event.TreeExpansionListener;

import javax.swing.event.TreeModelListener;

import javax.swing.event.TreeSelectionEvent;

import javax.swing.event.TreeSelectionListener;

import javax.swing.filechooser.FileSystemView;

import javax.swing.tree.DefaultTreeCellRenderer;

import javax.swing.tree.TreeModel;

import javax.swing.tree.TreePath;



public class FileTree extends JTree {

static final long serialVersionUID = 0;



private FileList theList;



public FileTree(FileList list) {

theList = list;

setModel(new FileSystemModel(new FolderNode()));

this.setCellRenderer(new FolderRenderer());



addTreeSelectionListener(new TreeSelectionListener() {

public void valueChanged(TreeSelectionEvent tse) {

}

});



this.setSelectionRow(0);

}



public void fireValueChanged(TreeSelectionEvent tse) {

TreePath tp = tse.getNewLeadSelectionPath();

Object o = tp.getLastPathComponent();

// theList.fireTreeSelectionChanged((PathNode)o);

theList.fireTreeSelectionChanged((FolderNode) o);

}



public void fireTreeCollapsed(TreePath path) {

super.fireTreeCollapsed(path);

TreePath curpath = getSelectionPath();



if (path.isDescendant(curpath)) {

setSelectionPath(path);

}

}



public void fireTreeWillExpand(TreePath path) {

System.out.println("Path will expand is " + path);

}



public void fireTreeWillCollapse(TreePath path) {

System.out.println("Path will collapse is " + path);

}



class ExpansionListener implements TreeExpansionListener {

FileTree tree;



public ExpansionListener(FileTree ft) {

tree = ft;

}



public void treeCollapsed(TreeExpansionEvent tee) {

}



public void treeExpanded(TreeExpansionEvent tee) {

}

}

}



class FileSystemModel implements TreeModel {

I_fileSystem theRoot;



char fileType = I_fileSystem.DIRECTORY;



public FileSystemModel(I_fileSystem fs) {

theRoot = fs;

}



public Object getRoot() {

return theRoot;

}



public Object getChild(Object parent, int index) {

return ((I_fileSystem) parent).getChild(fileType, index);



}



public int getChildCount(Object parent) {

return ((I_fileSystem) parent).getChildCount(fileType);

}



public boolean isLeaf(Object node) {

return ((I_fileSystem) node).isLeaf(fileType);

}



public int getIndexOfChild(Object parent, Object child) {

return ((I_fileSystem) parent).getIndexOfChild(fileType, child);

}



public void valueForPathChanged(TreePath path, Object newValue) {

}



public void addTreeModelListener(TreeModelListener l) {

}



public void removeTreeModelListener(TreeModelListener l) {

}

}



interface I_fileSystem {

final public static char DIRECTORY = 'D';



final public static char FILE = 'F';



final public static char ALL = 'A';



public Icon getIcon();



public I_fileSystem getChild(char fileType, int index);



public int getChildCount(char fileType);



public boolean isLeaf(char fileType);



public int getIndexOfChild(char fileType, Object child);

}



/**

* A data model for a JTree. This model explorer windows file system directly.

*

* <p>

* Perhaps there is a fatal bug with this design. For speed, each of instances

* of this model contains file objects of subdirectory, up to now, there isn't

* any method to release them until program be end. I'm afraid that the memory

* would be full of if the file system is large enough and JVM memery size

* setted too small.

*

* <p>

* I won't pay more attention to solve it. it isn't goal of current a exercise.

*

* @author Jason

*/

class FolderNode implements I_fileSystem {



// private static FolderNode theRoot;

private static FileSystemView fsView;



private static boolean showHiden = true;;



private File theFile;



private Vector<File> all = new Vector<File>();



private Vector<File> folder = new Vector<File>();



/**

* set that whether apply hiden file.

*

* @param ifshow

*/

public void setShowHiden(boolean ifshow) {

showHiden = ifshow;

}



public Icon getIcon() {

return fsView.getSystemIcon(theFile);

}



public String toString() {

// return fsView.

return fsView.getSystemDisplayName(theFile);

}



/**

* create a root node. by default, it should be the DeskTop in window file

* system.

*

*/

public FolderNode() {

fsView = FileSystemView.getFileSystemView();

theFile = fsView.getHomeDirectory();

prepareChildren();

}



private void prepareChildren() {

File[] files = fsView.getFiles(theFile, showHiden);



for (int i = 0; i < files.length; i++) {

all.add(files[i]);

if (files[i].isDirectory()

&& !files[i].toString().toLowerCase().endsWith(".lnk")) {



folder.add(files[i]);

}

}

}



private FolderNode(File file) {

theFile = file;

prepareChildren();

}



public FolderNode getChild(char fileType, int index) {

if (I_fileSystem.DIRECTORY == fileType) {

return new FolderNode(folder.get(index));

} else if (I_fileSystem.ALL == fileType) {

return new FolderNode(all.get(index));

} else if (I_fileSystem.FILE == fileType) {

return null;

} else {

return null;

}



}



public int getChildCount(char fileType) {

if (I_fileSystem.DIRECTORY == fileType) {

return folder.size();

} else if (I_fileSystem.ALL == fileType) {

return all.size();

} else if (I_fileSystem.FILE == fileType) {

return -1;

} else {

return -1;

}

}



public boolean isLeaf(char fileType) {

if (I_fileSystem.DIRECTORY == fileType) {

return folder.size() == 0;

} else if (I_fileSystem.ALL == fileType) {

return all.size() == 0;

} else if (I_fileSystem.FILE == fileType) {

return true;

} else {

return true;

}

}



public int getIndexOfChild(char fileType, Object child) {

if (child instanceof FolderNode) {

if (I_fileSystem.DIRECTORY == fileType) {

return folder.indexOf(((FolderNode) child).theFile);

} else if (I_fileSystem.ALL == fileType) {

return all.indexOf(((FolderNode) child).theFile);

} else if (I_fileSystem.FILE == fileType) {

return -1;

} else {

return -1;

}

} else {

return -1;

}

}

}



class FolderRenderer extends DefaultTreeCellRenderer {

private static final long serialVersionUID = 1L;

public Component getTreeCellRendererComponent(JTree tree, Object value,

boolean sel, boolean expanded, boolean leaf, int row,

boolean hasFocus) {



I_fileSystem node = (I_fileSystem) value;

Icon icon = node.getIcon();



setLeafIcon(icon);

setOpenIcon(icon);

setClosedIcon(icon);



return super.getTreeCellRendererComponent(tree, value, sel, expanded,

leaf, row, hasFocus);

}

}


=========================================================
// JExplorer.java

package tl.exercise.swing;



import java.awt.BorderLayout;

import java.awt.Dimension;

import java.awt.Toolkit;



import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JSplitPane;

import javax.swing.border.BevelBorder;



public class JExplorer {

public static void main(String[] args) {

//JFrame.setDefaultLookAndFeelDecorated(true);

JFrame frame = new JFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



frame.getContentPane().add(new UI(frame));



frame.pack();



Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();

int left = (screen.width - frame.getWidth()) / 2;

int top = (screen.height - frame.getHeight()) / 2;



frame.setLocation(left, top);



frame.setVisible(true);

}

}



class UI extends JPanel {

//implements I_menuHandler{

static final long serialVersionUID = 0l;



static int LEFT_WIDTH = 200;



static int RIGHT_WIDTH = 300;



static int WINDOW_HEIGHT = 300;



JFrame frame = null;



public UI(JFrame frame) {

//EmptyBorder eb = new EmptyBorder(1,1,1,1);



this.frame = frame;

setPreferredSize(new Dimension(800, 600));



setBorder(new BevelBorder(BevelBorder.LOWERED));



setLayout(new BorderLayout());



FileList list = new FileList();

FileTree tree = new FileTree(list);

tree.setDoubleBuffered(true);

list.setDoubleBuffered(true);



JScrollPane treeView = new JScrollPane(tree);

treeView.setPreferredSize(

new Dimension(LEFT_WIDTH, WINDOW_HEIGHT));

JScrollPane listView = new JScrollPane(list);

listView.setPreferredSize(

new Dimension(RIGHT_WIDTH, WINDOW_HEIGHT));



JSplitPane pane =

new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeView,

listView);

pane.setDividerLocation(300);

pane.setDividerSize(4);

//pane.setDoubleBuffered(true);



add(pane);

}

}


==========================================================
// FileList.java

package tl.exercise.swing;

import java.awt.Color;

import java.awt.Component;

import javax.swing.JLabel;

import javax.swing.JList;

import javax.swing.ListCellRenderer;

import javax.swing.ListModel;

import javax.swing.event.ListDataListener;



public class FileList

extends JList{

//PathNode theNode;

FileListModel dataModel;

static final long serialVersionUID = 10;

public FileList() {

dataModel = new FileListModel();

setModel(dataModel);

this.setCellRenderer(new MyCellRenderer());

}

public void fireTreeSelectionChanged(I_fileSystem node) {

//Vector files = node.getFiles();

//theNode = node;

dataModel.setNode(node);

updateUI();

}

}



class FileListModel

implements ListModel {

FileList theList;

I_fileSystem node;

char fileType = I_fileSystem.ALL;



public void setNode (I_fileSystem node) {

this.node = node;

}



public Object getElementAt(int index) {

if (node != null) {

return ((I_fileSystem)node).getChild(fileType, index);

} else {

return null;

}

}



public int getSize() {

if (node != null) {

return ((I_fileSystem)node).getChildCount(fileType);

} else {

return 0;

}

}



public void addListDataListener(ListDataListener l) {

}

public void removeListDataListener(ListDataListener l) {

}

}



class MyCellRenderer extends JLabel implements ListCellRenderer {

public MyCellRenderer() {

setOpaque(true);

}

public Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus)

{

FolderNode node = (FolderNode)value;

setIcon(node.getIcon());

setText(value.toString());

setBackground(isSelected ? Color.BLUE.darker().darker(): Color.WHITE);

setForeground(isSelected ? Color.WHITE : Color.BLACK);

return this;

}

}
################19/12/2007更新################### 新添加/重写的功能: 1. 已实现简单的剪切/复制/粘贴功能(尚不能和外界程序交互) 2. 添加创建新文件夹功能 3. 添加选择全部/文件/文件夹功能 4. 增加对创建新文件夹,重命名,删除,粘贴操作的异常处理 5. FileUtil中增加getFileCentent方法,用于读取文本文件内容 6. 重写AboutDialog 7. 重写ExitAction 8. 重写FileUtil中doPaste()方法,显著提高速度,修正拷贝文件时会导致文件不正常的严重Bug 9. 修正其他部分已发现Bug 10. 版本号升级为0.5 尚未实现的功能: 1. 与外界程序的交互 2. 拖拽 3. 国际化 4. 输入文件名时对特殊字符的验证 ################17/12/2007更新################### 新添加/重写的功能: 1. 排序功能已加入菜单栏和弹出菜单 2. 重写图标载入方法,已经可以实现图标动态载入和识别 3. 重写TableViewer中tableColumn生成载入方法,已经可以实现tablecolumn的半动态载入和识别 4. 实现动态识别文件类型 5. 进行删除操作时,对删除的文件进行识别 6. 更新添加了一些FileUtil中的方法,并且把这个类的注释写的差不多了 - - 注意: 1. icons文件夹内的文件结构有变化。 2. jar文件没有更新,如果需要打好包的jar文件请等我把功能都实现后的那个版本 - - 尚未实现的功能: 1. 剪切/复制/粘贴功能 2. 拖拽功能 3. 详尽的注释 4. 异常处理 5. 国际化 ################14/12/2007更新################### 已经实现的基本功能: 1. 树形浏览结构 2. 双击 运行程序/进入下一级菜单目录 3. 返回上一级菜单 4. 重命名 5. 刷新 6. 删除 7. 按文件名/大小/类型/最后修改日期排序 8. 对当前文件夹进行过滤操作 9. 对当前文件夹的简要统计 尚未实现的功能: 1. 剪切/复制/粘贴 2. 拖拽 3. 弹出菜单中的排序选项 4. 动态识别文件类型 5. 详尽的注释 已知的Bug: 1. TreeViewer进行目录切换时,TableViewer窗体有时会变成空白 2. 有特殊字符的过滤操作将导致异常 3. 重命名没有考虑特殊字符 4. 有大量文件(几百个以上)的目录会打开的很慢 5. 文件删除失败时没有提示###### 新添加/重写的功能: 1. 已实现简单的剪切/复制/粘贴功能(尚不能和外界程序交互) 2. 添加创建新文件夹功能 3. 添加选择全部/文件/文件夹功能 4. 重写AboutDialog 5. 增加对创建新文件夹,重命名,删除,粘贴操作的异常处理 6. 重写ExitAction 7. 修正部分已发现Bug 尚未实现的功能: 1. 与外界程序的交互 2. 拖拽 3. 国际化 4. 输入文件名时对特殊字符的验证
作者:talent_marquis邮件:talent_marquis@163.com################19/12/2007更新###################新添加/重写的功能:1. 已实现简单的剪切/复制/粘贴功能(尚不能和外界程序交互)2. 添加创建新文件夹功能3. 添加选择全部/文件/文件夹功能4. 增加对创建新文件夹,重命名,删除,粘贴操作的异常处理5. FileUtil中增加getFileCentent方法,用于读取文本文件内容6. 重写AboutDialog7. 重写ExitAction8. 重写FileUtil中doPaste()方法,显著提高速度,修正拷贝文件时会导致文件不正常的严重Bug9. 修正其他部分已发现Bug10. 版本号升级为0.5尚未实现的功能:1. 与外界程序的交互2. 拖拽3. 国际化4. 输入文件名时对特殊字符的验证################17/12/2007更新###################新添加/重写的功能:1. 排序功能已加入菜单栏和弹出菜单2. 重写图标载入方法,已经可以实现图标动态载入和识别3. 重写TableViewer中tableColumn生成载入方法,已经可以实现tablecolumn的半动态载入和识别4. 实现动态识别文件类型5. 进行删除操作时,对删除的文件进行识别6. 更新添加了一些FileUtil中的方法,并且把这个类的注释写的差不多了 - -注意:1. icons文件夹内的文件结构有变化。2. jar文件没有更新,如果需要打好包的jar文件请等我把功能都实现后的那个版本 - -尚未实现的功能:1. 剪切/复制/粘贴功能2. 拖拽功能3. 详尽的注释4. 异常处理5. 国际化################14/12/2007更新###################已经实现的基本功能:1. 树形浏览结构2. 双击 运行程序/进入下一级菜单目录3. 返回上一级菜单4. 重命名5. 刷新6. 删除7. 按文件名/大小/类型/最后修改日期排序8. 对当前文件夹进行过滤操作9. 对当前文件夹的简要统计尚未实现的功能:1. 剪切/复制/粘贴2. 拖拽3. 弹出菜单中的排序选项4. 动态识别文件类型5. 详尽的注释已知的Bug:1. TreeViewer进行目录切换时,TableViewer窗体有时会变成空白2. 有特殊字符的过滤操作将导致异常3. 重命名没有考虑特殊字符4. 有大量文件(几百个以上)的目录会打开的很慢5. 文件删除失败时没有提示######新添加/重写的功能:1. 已实现简单的剪切/复制/粘贴功能(尚不能和外界程序交互)2. 添加创建新文件夹功能3. 添加选择全部/文件/文件夹功能4. 重写AboutDialog5. 增加对创建新文件夹,重命名,删除,粘贴操作的异常处理6. 重写ExitAction7. 修正部分已发现Bug尚未实现的功能:1. 与外界程序的交互2. 拖拽3. 国际化4. 输入文件名时对特殊字符的验证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值