Рекомендуется использовать org.openide.nodes.ChildFactory
для создания дочерних узлов, если у вас нет особой необходимости использовать один из Children
API.Но для общих случаев достаточно ChildFactory
.
При использовании Nodes API следует иметь в виду, что только оболочка вашей модели, которая используется в сочетании с API-интерфейсом Explorer, делает его доступным для различных компонентов представления в платформе NetBeans, таких каккак org.openide.explorer.view.BeanTreeView
.
Используя модель с именем MyModel
, которая может выглядеть примерно так:
public class MyModel {
private String title;
private List<MyChild> children;
public MyModel(List<MyChild> children) {
this.children = children;
}
public String getTitle() {
return title;
}
public List<MyChild> getChildren() {
return Collections.unmodifiableList(children);
}
}
Вы можете создать ChildFactory<MyModel>
, который будет отвечать за создание ваших узлов:
public class MyChildFactory extends ChildFactory<MyModel> {
private List<MyModel> myModels;
public MyChildFactory(List<MyModel> myModels) {
this.myModels = myModels;
}
protected boolean createKeys(List<MyModel> toPopulate) {
return toPopulate.addAll(myModels);
}
protected Node createNodeForKey(MyModel myModel) {
return new MyNode(myModel);
}
protected void removeNotify() {
this.myModels= null;
}
}
Затем реализуем MyNode
, который является слоем представления и оболочкой MyModel
:
public class MyNode extends AbstractNode {
public MyNode(MyModel myModel) {
this(myModel, new InstanceContent());
}
private MyNode(MyModel myModel, InstanceContent content) {
super(Children.create(
new MyChildrenChildFactory(myModel.getChildren()), true),
new AbstractLookup(content)); // add a Lookup
// add myModel to the lookup so you can retrieve it latter
content.add(myModel);
// set the name used in the presentation
setName(myModel.getTitle());
// set the icon used in the presentation
setIconBaseWithExtension("com/my/resouces/icon.png");
}
}
А теперь MyChildrenChildFactory
, который очень похож на MyChildFactory
, за исключением того, что он принимает List<MyChild>
и в свою очередь создает MyChildNode
:
public class MyChildFactory extends ChildFactory<MyChild> {
private List<MyChild> myChildren;
public MyChildFactory(List<MyChild> myChildren) {
this.myChildren = myChildren;
}
protected boolean createKeys(List<MyChild> toPopulate) {
return toPopulate.addAll(myChildren);
}
protected Node createNodeForKey(MyChild myChild) {
return new MyChildNode(myChild);
}
protected void removeNotify() {
this.myChildren = null;
}
}
Затем реализация MyChildNode
, которая очень похожа на MyNode
:
public class MyChildNode extends AbstractNode {
public MyChildNode(MyChild myChild) {
// no children and another way to add a Lookup
super(Children.LEAF, Lookups.singleton(myChild));
// set the name used in the presentation
setName(myChild.getTitle());
// set the icon used in the presentation
setIconBaseWithExtension("com/my/resouces/child_icon.png");
}
}
И нам понадобится детская модель, MyChild
, который очень похож на MyModel
:
public class MyChild {
private String title;
public String getTitle() {
return title;
}
}
Наконец, чтобы использовать все это, например, с BeanTreeView
, который будет находиться в TopComponent
, который реализует org.openide.explorer.ExplorerManager.Provider
:
// somewhere in your TopComponent's initialization code:
List<MyModel> myModels = ...
// defined as a property in you TC
explorerManager = new ExplorerManager();
// this is the important bit and we're using true
// to tell it to create the children asynchronously
Children children = Children.create(new MyChildFactory(myModels), true);
explorerManager.setRootContext(new AbstractNode(children));
Обратите внимание, что вам не нужно прикасаться к BeanTreeView
, и фактически это может быть любой компонент представления, включенный в платформу.Это рекомендуемый способ создания узлов, и, как я уже говорил, использование узлов используется в качестве уровня представления для использования в различных компонентах, включенных в платформу.
Если вам необходимо получитьребенок, вы можете использовать ExplorerManager
, который вы можете извлечь из TopComponent
, используя метод ExplorerManager.Provier.getExplorerManager()
, который был реализован из-за того, что ваш TopComponent
реализовал ExplorerManager.Provider
и фактически является тем способом, которым компонент представлениясам получает узлы:
ExplorerManager explorerManager = ...
// the AbstractNode from above
Node rootContext = explorerManager.getRootContext();
// the MyNode(s) from above
Children children = rootContext.getChildren().getNodes(true);
// looking up the MyModel that we added to the lookup in the MyNode
MyModel myModel = nodes[0].getLookup().lookup(MyModel.class);
Однако вы должны знать, что использование метода Children.getNodes(true)
для получения ваших узлов приведет к созданию всех ваших узлов и их дочерних элементов;который не был создан из-за того, что мы сказали фабрике, что хотим, чтобы она создавала дочерние элементы асинхронно.Это не рекомендуемый способ доступа к данным, но вместо этого вам следует сохранить ссылку на List<MyModel>
и использовать ее, если это вообще возможно.Из документации Children.getNodes(boolean)
:
... в общем, если вы пытаетесь получить полезные данные, вызывая этот метод, вы, вероятно, делаете что-то не так.Обычно вам следует запрашивать информацию у некоторой базовой модели, а не у детей.
Опять же, вы должны помнить, что Nodes API - это уровень представления и используется в качестве адаптера между вашей моделью и вашимviews.
Когда это становится мощной техникой, используется один и тот же ChildFactory
в разных и разных видах.Вы можете использовать приведенный выше код во многих TopComponents
без каких-либо изменений.Вы также можете использовать FilterNode
, если вам нужно изменить только часть представления узла, не касаясь исходного узла.
Изучение API узлов является одним из наиболее сложных аспектов изученияAPI платформы NetBeans, как вы, несомненно, обнаружили.Как только вы овладеете этим API, вы сможете использовать гораздо больше встроенных возможностей платформ.
Для получения дополнительной информации об API-узлах см. Следующие ресурсы: