我正在使用javadoc中描述的GWT CellTree
复杂示例。但要打开树节点,我必须单击节点左侧的小箭头。我想通过点击文本打开树。我搜索了一些帮助,发现我可以使用ClickableTextCell
。真的说,我不明白从哪里开始。你能帮助我或提供其他解决方案吗?我希望该节点看起来像一个锚:当我在文本上鼠标时,光标变为指针,文本下划线。
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) {
ListDataProvider<Composer> dataProvider = new ListDataProvider<CellTreeExample2.Composer>(
composers);
Cell<Composer> cell = new AbstractCell<Composer>() {
@Override
public void render(Context context, Composer value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped(value.getName());
}
}
};
return new DefaultNodeInfo<Composer>(dataProvider, cell);
} else if (value instanceof Composer) {
ListDataProvider<Playlist> dataProvider = new ListDataProvider<Playlist>(
((Composer) value).getPlaylists());
Cell<Playlist> cell = new AbstractCell<Playlist>() {
@Override
public void render(Context context, Playlist value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped(value.getName());
}
}
};
return new DefaultNodeInfo<Playlist>(dataProvider, cell);
} else if (value instanceof Playlist) {
ListDataProvider<String> dataProvider = new ListDataProvider<String>(
((Playlist) value).getSongs());
return new DefaultNodeInfo<String>(dataProvider, new TextCell(),
selectionModel, null);
}
return null;
}
public boolean isLeaf(Object value) {
if (value instanceof String) {
return true;
}
return false;
}
答案 0 :(得分:1)
您必须使用Cell来捕获单元格上的点击(如ClickableTextCell)。 在我的项目中,我只为树的第一层实现了这个系统:
Cell<String> nodeCell = new AbstractCell<String>("click", "keydown") {
@Override
public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event, ValueUpdater<String> valueUpdater) {
String eventType = event.getType();
// Special case the ENTER key for a unified user experience.
if ("click".equals(eventType) || ("keydown".equals(eventType) && event.getKeyCode() == KeyCodes.KEY_ENTER)) {
tree.getRootTreeNode().setChildOpen(context.getIndex(), !tree.getRootTreeNode().isChildOpen(context.getIndex()));
}
}
@Override
public void render(Cell.Context context, String value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendEscaped(value);
}
}
};
要打开更多关卡,必须在级联中使用setChildOpen:
tree.getRootTreeNode().setChildOpen(1, true).setChildOpen(1, true).setChildOpen(1, true);
答案 1 :(得分:1)
因为您可能不希望这些节点也可以选择,所以我会使用NoSelectionModel
。
每当您点击这些节点时,请在父setChildOpen()
上调用TreeNode
以切换其状态。要获取父TreeNode
,请在祖父母setChildOpen(index, true)
上使用TreeNode
(递归到getRootTreeNode()
:因为您知道该节点已经加载并且已打开(您&#39} ;重新响应子节点上的事件),您可以确保setChildOpen
将返回TreeNode
而不是null
。
最后,要让index
传递给setChildOpen
方法,只需在父&#34;域对象&#34;的子列表中使用indexOf()
(即composers.indexOf(composer)
,composer.getPlaylists().indexOf(playlist)
等。这假设您可以通过维护双向关系(playlist.getComposer().getPlaylists().indexOf(playlist)
)或通过构建子映射来轻松获取给定对象(给定播放列表的作曲家)的父 →父母关系。
以下是您要从NoSelectionModel
SelectionHandler
拨打的一些构建基块:
void toggleComposerOpen(Composer composer) {
int index = composers.indexOf(composer);
TreeNode rootTreeNode = tree.getRootTreeNode();
rootTreeNode.setChildOpen(index, !rootTreeNode.isChildOpen(index));
}
void togglePlaylistOpen(Playlist playlist) {
Composer composer = playlist.getComposer();
TreeNode composerTreeNode = getTreeNode(composer);
int index = composer.getPlaylist().indexOf(playlist);
composer.setChildOpen(index, !composer.isChildOpen(index));
}
private void TreeNode getTreeNode(Composer composer) {
int index = composers.indexOf(composer);
return tree.getRootTreeNode().setChildOpen(index, true);
}
答案 2 :(得分:1)
使用SingleSelectionModel
并将其传递到DefaultNodeInfo
。添加onSelectionChanged
处理程序,以便在调用它时:
ListDataProvider
中找到项目的索引,这将用于打开关联的子索引CellTree
根TreeNode
打开关联的子索引onSelectionChanged
事件将再次触发。这将模拟切换。addSelectionChangeHandler
添加选择更改处理程序。
composerSingleSelectionModel = new SingleSelectionModel<Composer>(COMPOSER_KEY_PROVIDER);
// ...
composerSingleSelectionModel.addSelectionChangeHandler(
new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
final TreeNode rootTreeNode = cellTree.getRootTreeNode();
final Composer selectedComposer = composerSingleSelectionModel.getSelectedObject();
if (selectedComposer == null) return;
final int index = composerListDataProvider.getList().indexOf(selectedComposer);
if (index < 0) return;
final boolean isOpen = rootTreeNode.isChildOpen(index);
rootTreeNode.setChildOpen(index, !isOpen);
/* Clear what is currently selected, so that
* onSelectionChange is fired again when the same item is
* selected consecutively.
*/
composerSingleSelectionModel.clear();
}
});
TreeViewModel
将作曲家选择模型传递给自定义TreeViewModel
。
public class MusicTreeViewModel implements TreeViewModel {
// Define constructor to pass in properties ...
@Override
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) {
return new DefaultNodeInfo<Composer>(composerListDataProvider, composerCell, composerSelectionModel, null);
} else if (value instanceof Composer) {
final Composer composer = (Composer) value;
final Object composerKey = composerListDataProvider.getKey(composer);
final ListDataProvider<Playlist> playlistListDataProvider = getPlaylistListDataProvider(composerKey);
return new DefaultNodeInfo<Playlist>(playlistListDataProvider, playlistCell, playlistSelectionModel, null);
} else {
throw new IllegalArgumentException(
"Unsupported object type: " + value.getClass().getName());
}
}
@Override
public boolean isLeaf(Object value) {
if (value instanceof Composer) {
return ((Composer) value).getPlaylists().isEmpty();
} else if (value instanceof Playlist) {
return true;
}
return false;
}
}