版权声明:转载时请务必保留以下作者信息和链接
作者:陈维(chenweionline@hotmail.com)作者的网站:http://www.chenwei.mobi
在 NetBeans Platform (以后简称 NP)里,Node 负责提供内容在界面组件里的表现,Tree 、 List 、Palette、Property Sheet 等界面组件都和 Node 有关,所以 Node 结构的设计对于内容在界面上表现十分重要。这篇文章我试图通过构建一个类似 Windows 资源管理器上的磁盘文件树的模块样例程序,来说明如何使用 Node API 结合 NP 界面组件创建桌面应用。
我假设读者已经了解如何建立一个 NetBeans 模块,直接进入正题。
NP提供了一系列可重用的组件供开发者使用,BeanTreeView就是其中之一。事实上,无论是使用 BeanTreeView还是 Swing 中的 JTree 编写一个磁盘文件树,首先要确定节点(目录)和子节点(子目录)的查询结构。下面我们首先创建磁盘文件树对应的 Node 体系结构。
1、设计 Node
根据我们的需求(磁盘文件树),我们需要设计一个 Node 用来表现驱动器、文件夹、文件以及特殊文件夹(例如“桌面”),整个文件系统会构建许多 Node。通过这些分析,在项目引用的库中导入 Node API 后(导入过程略)建立一个类 FileNode。
package
mobi.chenwei.nbm.explorer;
import
java.awt.Image;
import
java.io.File;
import
java.io.FileFilter;
import
javax.swing.ImageIcon;
import
javax.swing.filechooser.FileSystemView;
import
org.openide.nodes.AbstractNode;

/***/
/**
*文件节点。用于表现驱动器、文件夹、文件以及特殊文件夹...
*
*@authorChenWei
*@websitewww.chenwei.mobi
*@emailchenweionline@hotmail.com
*/

public
class
FileNode
extends
AbstractNode
implements
Comparable
...
{
privatestaticFileSystemViewfileSystemView=FileSystemView.getFileSystemView();
privateFilefile;

publicFileNode(Filefile,FileFilterfilter)...{
super(newFileChildren(file,filter));
this.file=file;
}

publicintcompareTo(Objecto)...{
if(oinstanceofFileNode)...{
Filef1=getFile();
Filef2=((FileNode)o).getFile();
returnf1.compareTo(f2);
}
return0;
}

publicFilegetFile()...{
returnfile;
}

publicstaticFileNodecreateHomeNode(FileFilterfilter)...{
Filefile=fileSystemView.getHomeDirectory();
returnnewFileNode(file,filter);
}
@Override
publicStringgetHtmlDisplayName()...{
returnfileSystemView.getSystemDisplayName(getFile());
}
@Override
publicImagegetIcon(inttype)...{
//这里将Icon强制转换为ImageIcon在MacOSX平台上会抛出异常!
return((ImageIcon)fileSystemView.getSystemIcon(getFile())).getImage();
}
@Override
publicImagegetOpenedIcon(inttype)...{
//这里将Icon强制转换为ImageIcon在MacOSX平台上会抛出异常!
return((ImageIcon)fileSystemView.getSystemIcon(getFile())).getImage();
}
}
在 FileNode 里我们继承了 AbstractNode,它实现了抽象类 Node 的一些基本方法。同时,我们实现的 Comparable接口,它用来对于节点进行排序,之后我们还会提到。FileNode 里包含了它表示的 File 以及当前文件系统的 FileSystemView对象。通过覆写 getHtmlDisplayName(),getIcon() 和 getOpenedIcon() 来提供 Node 在界面上的具体表现(这里我需要说一些与 Node 无关的话,在 getIcon() 和 getOpenedIcon() 里我去的当前系统文件浏览器中显示的文件、目录或文件夹的图标然后强行转换成 ImageIcon,这里的强制转换在 Mac OS X 系统中会抛出异常,因为它并不是 ImageIcon 而是 ,我目前还不知道怎么取得Mac 文件系统中的文件图标)。另外,创建了一个静态方法 createHomeNode() 用来取得文件系统的根,可以看到其中包含一个文件过滤器,你可以定制这个文件过滤器来取得你需要的文件,在后面的代码中我实现了一个简单的文件夹过滤器。
大家可以看到 FileNode 的构造函数里有一个 FileChildren 的实例,我们通过它来完成完整的目录结构。好了,现在我们要为 FileNode 建立它的 Children。
package
mobi.chenwei.nbm.explorer;
import
java.io.File;
import
java.io.FileFilter;
import
java.util.ArrayList;
import
java.util.Collection;
import
org.openide.nodes.Children;
import
org.openide.nodes.Node;

/***/
/**
*FileNode的Children。
*
*@authorChenWei
*@websitewww.chenwei.mobi
*@emailchenweionline@hotmail.com
*/

public
class
FileChildren
extends
Children.SortedArray
...
{
privateFileparent;
privateFileFilterfilter;

publicFileChildren(Fileparent,FileFilterfilter)...{
this.parent=parent;
this.filter=filter;
}
@Override
protectedCollection<Node>initCollection()...{
File[]children=parent.listFiles();
ArrayList<Node>fileNodes=newArrayList<Node>();
for(Filef:children)...{
if(filter==null||filter.accept(f))...{
fileNodes.add(newFileNode(f,filter));
}
}
returnfileNodes;
}
}
实现 Children 一般都直接继承 Children.Array,Children.Map,Children.Keys,Children.SortedArray,Index.ArrayChildren 或 Children.SortedMap。FileChildren 继承了 Children.SortedArray,它可以管理 Node 排序,现在我们回过头看看实现了 Comparable接口的 FileNode,在 compareTo() 里定义了排序规则(通过比较两个 File 来)。当 Children 第一次被使用时,initCollection() 被调用,把文件夹中过滤出的子文件重新包装成 FileNode 并且将集合提交返回。
2、设计界面组件与 ExplorerManager
当我们设计完 Node 结构之后,我们来看一看界面上的表现。
首先通过向导创建 TopComponent 组件 ExplorerTopComponent(创建过程略),它是 NP 上的 Dockable Window。在项目引用的库中导入 Explorer & Property Sheet API 后(导入过程略)后我们在 ExplorerTopComponent 里创建 BeanTreeView 和 ExporerManager 的实例并且实现 ExporerManager.Provider接口,在 getExplorerManager() 中返回 ExporerManager 的实例。
final
class
ExplorerTopComponent
extends
TopComponent
implements
ExplorerManager.Provider
...
{
privateBeanTreeViewfileTree;
privateExplorerManagerexplorerMgr;

privateExplorerTopComponent()...{
//........
myInit();
}
//........


privatevoidmyInit()...{
fileTree=newBeanTreeView();
explorerMgr=newExplorerManager();
add(fileTree,BorderLayout.CENTER);
this.associateLookup(ExplorerUtils.createLookup(explorerMgr,getActionMap()));
explorerMgr.setRootContext(FileNode.createHomeNode(newDirFilter()));
//explorerMgr.setRootContext(FileNode.createHomeNode(null));
}

publicExplorerManagergetExplorerManager()...{
returnexplorerMgr;
}
}
从上面的代码,我们看到 myInit() 里具体实例化了 BeanTreeView 和 ExploterManager,将 BeanTreeView 加入面板中央区域,然后通过 associateLookup() 和 ExplorerUtils.createLookup() 建立了一个属于 explorerMgr 的Lookup。再通过 FileNode.createHomeNode() 创建了它的根。构造根 Node 时传入了一个文件夹过滤器,从而使 BeanTreeView 中只显示非隐藏的文件夹。
package
mobi.chenwei.nbm.explorer;
import
java.io.File;
import
java.io.FileFilter;
import
java.io.Serializable;

/***/
/**
*文件操作中的文件夹过滤器类。
*
*@authorChenWei
*@websitewww.chenwei.mobi
*@emailchenweionline@hotmail.com
*/

public
class
DirFilter
implements
FileFilter,Serializable
...
{
//是否过滤隐藏文件夹。
privatebooleanfiltrateHidden=false;

publicbooleanaccept(Filepathname)...{
if(pathname.isDirectory())...{
if(isFiltrateHidden()&&pathname.isHidden())...{
returnfalse;
}else...{
returntrue;
}
}else...{
returnfalse;
}
}

publicbooleanisFiltrateHidden()...{
returnfiltrateHidden;
}

publicvoidsetFiltrateHidden(booleanhidden)...{
this.filtrateHidden=hidden;
}
}
现在一个磁盘文件树就完成了,可以在模块项目上点击鼠标右键,选择 "Install/Reload in Target Platform" 项执行观看效果。

完整模块源码下载:
本文介绍如何在NetBeans Platform中使用Node API结合界面组件创建类似Windows资源管理器的磁盘文件树。通过设计FileNode类及其Children,实现文件系统的可视化展现。

4527

被折叠的 条评论
为什么被折叠?



