像普通树一样使用 Vaadin TreeTable

Use Vaadin TreeTable like a normal Tree

由于 Vaadin Tree 不支持延迟加载我想使用 TreeTable.
TreeTable 应该看起来像一棵普通的树,没有 headers 和斑马线样式。

这是我目前得到的:

TreeTable mainTree = new TreeTable();
mainTree.setSizeFull();
mainTree.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
mainTree.setColumnCollapsingAllowed(false);

我还应该设置什么以及如何去除斑马纹?

考虑自己实现一个延迟加载机制,其中加载三个根。然后添加一个 ExpandListener,它在调用时加载子对象并将它们添加到节点。

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        setContent(layout);

        final Tree t = new Tree();
        t.addItem(new TreeNode(0));
        t.addExpandListener(new ExpandListener() {

            @Override
            public void nodeExpand(ExpandEvent event) {
                TreeNode node = (TreeNode) event.getItemId();
                for (TreeNode child : node.getMyChildren()){
                    t.addItem(child);
                    t.setParent(child, node);
                }
            }
        });
        layout.addComponent(t);
    }

}

尽管在 Vaadin 文档中说 Tree 的延迟加载是 not supported,但我设法实现了以下 延迟加载 Hierarchical接口。

将所有元素存储在本地结构中非常重要(在我的例子中是 HashMap hierarchy),不要多次读取元素这是行不通的。我认为是因为 Vaadin 不使用 equals()hashCode().

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.softmodeler.common.CommonPlugin;
import com.softmodeler.model.OutputNode;
import com.softmodeler.service.IViewService;
import com.vaadin.data.Container.Hierarchical;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.BeanItem;

/**
 * @author Flavio Donzé
 * @version 1.0
 */
public class OutputNodeHierachical implements Hierarchical {
    private static final long serialVersionUID = 8289589835030184018L;

    /** the view service */
    private IViewService service = CommonPlugin.getService(IViewService.class);

    /** collection of all root nodes */
    private List<OutputNode> rootNodes = null;
    /** parent=>children mapping */
    private Map<OutputNode, List<OutputNode>> hierarchy = new HashMap<>();

    /**
     * constructor
     *
     * @param rootNodes collection of all root nodes
     */
    public OutputNodeHierachical(List<OutputNode> rootNodes) {
        this.rootNodes = Collections.unmodifiableList(rootNodes);

        addToHierarchy(rootNodes);
    }

    @Override
    public Collection<?> getChildren(Object itemId) {
        try {
            List<OutputNode> children = hierarchy.get(itemId);
            if (children == null) {
                OutputNode node = (OutputNode) itemId;
                children = service.getChildren(node.getNodeId(), false);

                hierarchy.put(node, children);

                // add children to hierarchy, their children will be added on click
                addToHierarchy(children);
            }
            return children;
        } catch (Exception e) {
            VaadinUtil.handleException(e);
        }
        return null;
    }

    /**
     * add each element to the hierarchy without their children hierarchy(child=>null)
     *
     * @param children elements to add
     */
    private void addToHierarchy(List<OutputNode> children) {
        for (OutputNode child : children) {
            hierarchy.put(child, null);
        }
    }

    @Override
    public boolean areChildrenAllowed(Object itemId) {
        return !((OutputNode) itemId).getChilds().isEmpty();
    }

    @Override
    public boolean hasChildren(Object itemId) {
        return !((OutputNode) itemId).getChilds().isEmpty();
    }

    @Override
    public Object getParent(Object itemId) {
        String parentId = ((OutputNode) itemId).getParentId();
        for (OutputNode node : hierarchy.keySet()) {
            if (node.getNodeId().equals(parentId)) {
                return node;
            }
        }
        return null;
    }

    @Override
    public Collection<?> rootItemIds() {
        return rootNodes;
    }

    @Override
    public boolean isRoot(Object itemId) {
        return rootNodes.contains(itemId);
    }

    @Override
    public Item getItem(Object itemId) {
        return new BeanItem<OutputNode>((OutputNode) itemId);
    }

    @Override
    public boolean containsId(Object itemId) {
        return hierarchy.containsKey(itemId);
    }

    @Override
    public Collection<?> getItemIds() {
        return hierarchy.keySet();
    }

    @Override
    public int size() {
        return hierarchy.size();
    }

    @Override
    public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Item addItem(Object itemId) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Object addItem() throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeItem(Object itemId) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeAllItems() throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Class<?> getType(Object propertyId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Collection<?> getContainerPropertyIds() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Property<?> getContainerProperty(Object itemId, Object propertyId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean addContainerProperty(Object propertyId, Class<?> type, Object defaultValue) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

}

像这样将容器添加到 Tree

OutputNodeHierachical dataSource = new OutputNodeHierachical(rootNodes);

Tree mainTree = new Tree();
mainTree.setSizeFull();
mainTree.setContainerDataSource(dataSource);
mainTree.addItemClickListener(new ItemClickListener() {
    private static final long serialVersionUID = -413371711541672605L;

    @Override
    public void itemClick(ItemClickEvent event) {
        OutputNode node = (OutputNode) event.getItemId();
        openObject(node.getObjectId());
    }
});