首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 第二书店 程序员
您的位置:NetBeans->NetBeans选择管理教程II—使用节点

NetBeans选择管理教程II—使用节点2008-01-10 来自:java060515  [收藏到我的网摘]

上一部教程介绍了在NetBeans中处理组件级选择的基本知识—如何从TopComponent的Lookup中提供对象,以及如何编写对获得焦点的组件的Lookup敏感的其他组件。

本教程侧重于Nodes API,它可以比组件级选择执行更加粒度化的视图和选择。当然,您可以编写一个组件,该组件可以根据需要读取和写入其自身的Lookup,并且这样可以提供更加粒度化的选择逻辑。但是Nodes API可以轻松执行该操作,并且与自己执行该操作相比,它提供了很多优势。

第一个优点是Nodes API提供一个表示层—采用某种方式编辑的数据模型和向用户公开该数据模型的UI组件之间的层。该层非常有用并且功能强大,因为可以采用多种方式或使用多个UI演示同一种模型。

第二个优点是Explorer API—模块org.openide.explorer提供一组丰富的组件—树、列表、三个表以及更多—这可以呈现Node及其子节点。

Node是一个普通的层次结构对象—一个Node具有:

l Children—其下面的层次结构中的节点,可以显示在树中

l Actions—一个操作数组,可以显示在弹出菜单中

l Display Name—一个人类可读的局部的显示名称,可以显示在UI组件中

l Icon—可以显示在UI组件中的图标

Node可以激活以上任何一項内容的更改,并且资源管理器UI组件将自动更新自身。这并不意味着上一部教程没有用—相反,它解释了Nodes API可以工作的原因。org.openide.nodes.Node具有一个getLookup()方法。实际上当您更改IDE中Projects选项卡的选择时发生了一些事情,例如Projects选项卡是TopComponent。它代理树中当前选择的对象的Lookup—就像Utilities.actionsGlobalContext() Lookup代理获得焦点的组件一样,并且当焦点改变时激活更改。

使用Explorer API中的组件,很容易创建您自己的Node树视图,并且使用非常少的代码在您自己的组件中拥有此类型的代理。查看器类型组件(如上一部教程中的MyViewer组件)不用执行其他任何特殊的操作便能够响应Explorer组件中的选择更改—当选择更改时将自动通知它们。

入门
本教程中的代码将延续上一部教程中的代码—假设您熟悉该代码以及其执行的操作。若要下载完整的示例,请访问http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=3146。

创建资源管理器视图
您将做的第一件事是对您的MyEditor编辑器组件进行一些实际修改。 首先从编辑器中打开它。

首先,显示My Editor项目的属性对话框。在Libraries选项卡上,单击add按钮,然后在对话框中键入“BeanTreeView”。当您看到列出了Explorer & Property Sheet API之后,单击OK,如下所示。这将在Explorer API模块上添加一个依赖性,以便您可以使用其中的类。


下一步,删除操作处理程序方法的主体部分:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
}
并从构造函数中删除对它的调用。这样,当您删除与其关联的按钮时,处理程序方法也将被删除。

切换到表单设计器,选择所有组件并删除它们。
在Component Inspector中,右键单击TopComponent节点,然后选择Set Layout > BorderLayout,如下所示:


单击Component Palette窗口中的JScrollPane按钮并将滚动窗格拖动到表单上—它将占据整个表单。此处的关键是所有Explorer UI组件都是JScrollPane的子类—因此您可以只更改实例化代码即可创建一个资源管理器视图。
选择您的JscrollPane,右键单击它,然后选择Customize Code。通过添加new BeanTreeView()来自定义Code Customizer中的初始行,如下所示:


BeanTreeView是Explorer API中的一个组件—在Node及其子节点之上的一个基本的基于JTree的视图,其中具有内置的弹出菜单处理、搜索以及更多操作。

切换到代码编辑器并按下Ctrl-Shift-I以导入BeanTreeView,因为需要添加导入语句,如下所示:


下一步是为您的树提供显示的内容。Explorer UI组件的工作类似于以下内容:当添加到某个容器时,它们搜索该容器及其祖先,直到它们找到实现ExplorerManager.Provider的容器为止。因此不要将该节点设置为直接在组件上查看—应该将其设置为在组件的管理器上查看。这样便可以拥有多个视图,主/详细信息视图以及由单个管理器管理的所有此类视图。按照如下方式添加MyEditor的签名:
public class MyEditor extends TopComponent implements ExplorerManager.Provider {
然后按下Ctrl-Shift-I修复导入。保留签名行中的插入符号,一个灯泡状的图案将出现在边缘。按下Alt-Enter并接受“Implement all abstract methods”提示。这将添加一个方法getExplorerManager()。按照如下方式实现该方法:

private final ExplorerManager mgr = new ExplorerManager();
public ExplorerManager getExplorerManager() {
return mgr;
}
现在,由于目标是一个可以显示多个APIObjects的组件,因此您需要一个或两个Node以显示在您的组件中。每个组件都将拥有自己的APIObject实例。因此,您现在将添加代码来为您的树视图创建一个根节点。向构造函数中添加以下行:
mgr.setRootContext(new AbstractNode(new MyChildren()));
上面的代码为MyEditor的子组件的所有资源管理器视图设置根节点。

如果您尝试Fix Imports,则可能会看到错误对话框,它告诉您AbstractNode或MyChildren都无法解析。若要解析AbstractNode,您需要在Nodes API模块上添加一个依赖性。右键单击My Editor项目,然后转到Libraries页面并单击Add Dependency。在Add对话框中键入“AbstractNode”,并且选中列表中的“Nodes API”项目时单击OK或按Enter键。
现在回到源编辑器中,按Ctrl-Shift-I键以执行Fix Imports。将通知您MyChildren无法解析。好了—您可以编写它了。
实现Node和Node子节点
您将注意到上面使用的类名为AbstractNode。尽管名称有所暗示,但它并不是抽象类!它是org.openide.nodes.Node的一种有用实现,可以节省很多时间和精力—而不是您自己实现Node,您可以只创建AbstractNode并将一个可为其提供子节点的Children对象传递给它,然后根据需要设置它的图标和显示名称。因此这是使Node对象表示某些内容的简单方法,无需为Node创建任何子类。

下一步是实现MyChildren,以便初始节点下面具有子节点。

右键单击My Editor项目中的org.myorg.myeditor包并从弹出菜单中选择New > Java Class。
在New Java Class向导中,将该类命名为“MyChildren”,然后单击Finish或按Enter键来创建该类。
修改该类的签名以便展开Children.Keys:
class MyChildren extends Children.Keys {
按Ctrl-Shift-I键执行Fix Imports
将插入符号放置到类签名行中。当空白处出现灯泡状图案时,按Alt-Enter键,然后再次按Enter键以接受“Implement all Abstract Methods”提示。这将添加一个createNodes (Object key)方法—这是您将创建节点的位置,这些节点将是您的根节点的子节点。
但是首先,您需要覆盖一个方法—addNotify。由于使用的是Swing组件中的addNotify()模式,因此Children.Keys.addNotify()将在第一次关注这个Children对象时得到调用—即第一次询问它的子节点。因此您可以延迟创建子Node,直到用户实际上已经在视图中展开了父节点并且需要查看子节点为止。将插入符号放置在源文件中的某个位置并按Alt-Insert键。然后选择“Override Method...”。在出现的对话框中,展开“Children”,选择addNotify()方法,然后单击OK或按Enter键。
实现addNotify()方法如下所示:
protected void addNotify() {
APIObject[] objs = new APIObject[5];
for (int i = 0; i < objs.length; i++) {
objs[i] = new APIObject();
}
setKeys (objs);
}
正如您从名称Children.Keys中所猜测的一样,您的父类所执行的操作就是获取一个数组或关键对象的Collection,并充当它们的Nodes的工厂。因此,您在addNotify()中调用setKeys(),因为addNotify()告诉您某些操作将询问子节点。对于数组中的每个元素或您传递给setKeys()的集合,都将调用一次createNodes()(请注意,这意味着如果必要的话可以让多个节点代表一个对象)。

现在您需要实现为所有这些节点实际创建Node对象的代码。按照如下代码实现createNodes():
protected Node[] createNodes(Object o) {
APIObject obj = (APIObject) o;
AbstractNode result = new AbstractNode (new MyChildren(), Lookups.singleton(obj));
result.setDisplayName (obj.toString());
return new Node[] { result };
}
按Ctrl-Shift-I键执行Fix Imports。
最后一步是安装一些管道代码,这些代码会将资源管理器连接到TopComponent的查找。首先,从类定义的前面删除以下行
private final InstanceContent content = new InstanceContent();
—您将使用一个实用工具将选定的Node的Lookup连接到您的组件的Lookup。

修改MyEditor的构造函数使它类似以下内容:
public MyEditor() {
initComponents();
associateLookup (ExplorerUtils.createLookup(mgr, getActionMap()));
mgr.setRootContext(new AbstractNode(new MyChildren()));
setDisplayName ("My Editor");
}

运行教程
您可能已经注意到,由于向创建的每个AbstractNode传递了MyChildren的一个新实例,因此最后您将看到一个具有无限深度的APIObject树—每个Node将有五个子Node,每个子Node都拥有其自己的APIObject。

现在您可以准备运行了,因此右键单击SelectionSuite并选择Clean and Build,然后再次右键单击并从弹出菜单中选择Run。当NetBeans启动时,使用File菜单上的Open Editor操作打开MyEditor的一个实例。

推荐人评论

上一部教程介绍了在NetBeans中处理组件级选择的基本知识—如何从TopComponent的Lookup中提供对象,以及如何编写对获得焦点的组件的Lookup敏感的其他组件。

用户评论

正在载入评论列表...

是谁推荐了此篇文章

专家头像付江CSDN频道编辑
个人blog发送信息
付江推荐的其他文章

热点新闻

热点评论

    精彩专题

    资源下载

      网站简介广告服务网站地图帮助联系方式诚聘英才English问题报告
    北京世纪乐知数码科技有限公司  版权所有  京 ICP 证 020026 号
    Copyright © 2000-2006, CSDN.NET, All Rights Reserved