现在的位置: 首页 > 综合 > 正文

NetBeans选择管理教程II—使用节点

2013年10月02日 ⁄ 综合 ⁄ 共 4218字 ⁄ 字号 评论关闭

上一部教程介绍了在NetBeans中处理组件级选择的基本知识如何从TopComponentLookup中提供对象以及如何编写对获得焦点的组件的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()方法实际上当您更改IDEProjects选项卡的选择时发生了一些事情,例如Projects选项卡是TopComponent它代理树中当前选择的对象的Lookup就像Utilities.actionsGlobalContext() Lookup代理获得焦点的组件一样并且当焦点改变时激活更改。

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

入门

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

创建资源管理器视图

您将做的第一件事是对您的MyEditor编辑器组件进行一些实际修改。 首先从编辑器中打开它。

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

  1. 下一步,删除操作处理程序方法的主体部分:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

}

并从构造函数中删除对它的调用。这样当您删除与其关联的按钮时处理程序方法也将被删除。

  1. 切换到表单设计器选择所有组件并删除它们。

  2. Component Inspector右键单击TopComponent节点然后选择Set Layout > BorderLayout如下所示

  1. 单击Component Palette窗口中的JScrollPane按钮并将滚动窗格拖动到表单上它将占据整个表单。此处的关键是所有Explorer UI组件都是JScrollPane的子类因此您可以只更改实例化代码即可创建一个资源管理器视图。

  2. 选择您的JscrollPane右键单击它然后选择Customize Code。通过添加new BeanTreeView()来自定义Code Customizer中的初始行如下所示

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

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

  1. 下一步是为您的树提供显示的内容。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;

}

  1. 现在由于目标是一个可以显示多个APIObjects的组件因此您需要一个或两个Node以显示在您的组件中。每个组件都将拥有自己的APIObject实例。因此,您现在将添加代码来为您的树视图创建一个根节点。向构造函数中添加以下行:

mgr.setRootContext(new AbstractNode(new MyChildren()));

上面的代码MyEditor的子组件的所有资源管理器视图设置根节点。

  1. 如果您尝试Fix Imports则可能会看到错误对话框它告诉您AbstractNodeMyChildren都无法解析。若要解析AbstractNode,您需要在Nodes API模块上添加一个依赖性。右键单击My Editor项目,然后转到Libraries页面并单击Add Dependency。在Add对话框中键入“AbstractNode”,并且选中列表中的“Nodes API”项目时单击OK或按Enter

  2. 现在回到源编辑器中Ctrl-Shift-I以执行Fix Imports将通知您MyChildren无法解析。好了您可以编写它了。

实现NodeNode子节点

您将注意到上面使用的类名为AbstractNode尽管名称有所暗示但它并不是抽象类它是org.openide.nodes.Node的一种有用实现,可以节省很多时间和精力而不是您自己实现Node您可以只创建AbstractNode并将一个可为其提供子节点的Children对象传递给它然后根据需要设置它的图标和显示名称。因此这是使Node对象表示某些内容的简单方法,无需为Node创建任何子类。

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

  1. 右键单击My Editor项目中的org.myorg.myeditor包并从弹出菜单中选择New > Java Class

  2. New Java Class向导中将该类命名为MyChildren”,然后单击Finish或按Enter来创建该类。

  3. 修改该类的签名以便展开Children.Keys

class MyChildren extends Children.Keys {

  1. Ctrl-Shift-I键执行Fix Imports

  2. 插入符号放置到类签名行中。当空白处出现灯泡状图案时Alt-Enter键,然后再次按Enter以接受Implement all Abstract Methods提示。这将添加一个createNodes (Object key)方法这是您将创建节点的位置,这些节点将是您的根节点的子节点。

  3. 但是首先您需要覆盖一个方法addNotify。由于使用的是Swing组件中的addNotify()模式因此Children.Keys.addNotify()将在第一次关注这个Children对象时得到调用第一次询问它的子节点。因此您可以延迟创建子Node,直到用户实际上已经在视图中展开了父节点并且需要查看子节点为止。将插入符号放置在源文件中的某个位置并按Alt-Insert。然后选择Override Method...在出现的对话框展开Children”,选择addNotify()方法,然后单击OK或按Enter

  4. 实现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()(请注意,这意味着如果必要的话可以让多个节点代表一个对象)。

  1. 现在您需要实现为所有这些节点实际创建Node对象的代码。按照如下代码实现createNodes()

protected Node[] createNodes(Object o) {

【上篇】
【下篇】

抱歉!评论已关闭.