GWT:右键单击选择一个TreeItem

时间:2010-04-25 16:57:53

标签: gwt select tree contextmenu

我正在捕获右键单击事件以显示上下文菜单。我无法弄清楚的是,在显示上下文菜单之前,如何使右键实际选择TreeItem。

感谢所有帮助。

 private Tree tree = new Tree() {
  @Override
  public void onBrowserEvent(Event event) {   
    if (event.getTypeInt() == Event.ONCONTEXTMENU) {
     DOM.eventPreventDefault(event);          
     showContextMenu(event);
    }   
   super.onBrowserEvent(event);
  }

  @Override
  protected void setElement(Element elem) {
   super.setElement(elem);
   sinkEvents(Event.ONCONTEXTMENU);
  }

 };

4 个答案:

答案 0 :(得分:1)

在ONCONTEXTMENU之前,

ONMOUSEDOWN事件被触发。您是否尝试过侦听onMouseDown事件,并设置所选项目?这些方面的东西:

@Override
public void onBrowserEvent(Event event) {   
switch (DOM.eventGetType(event)) {
    case Event.ONMOUSEDOWN:
        if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
            TreeItem selectedItem = findSelectedItem(event);
            if (selectedItem != null) {
                selectedItem.setSelected(true);
            }
        } else {
            super.onBrowserEvent(event);
        }
        break;
    case Event.ONCONTEXTMENU:
        showContextMenu(event);
        break;
    default:
        super.onBrowserEvent(event);
        break;
    }

并且findSelectedItem遍历树以查找所选项目:

TreeItem findSelectedItem(Event e) {
    return findSelectedItemRecursive(event.getClientX(), event.getClientY());
}

TreeItem findSelectedTreeItemRecursive(TreeItem root, int x, int y) {
    if (null == root) {
        int count = getItemCount();
        for (int i = 0; i < count; i++) {
            TreeItem selected = findSelectedTreeItemRecursive(getItem(i), x, y);
            if (selected != null) {
               return selected;
            }
        }
        return null;
    }
    int count = item.getChildCount();
    for (int i = 0; i < count; i++) {
        TreeItem selected = findSelectedTreeItem(item.getChild(i), x, y);
        if (selected != null) {
            return selected;
        }
    }

    if (x >= item.getAbsoluteLeft()
        && x <= item.getAbsoluteLeft() + item.getOffsetWidth()
        && y >= item.getAbsoluteTop()
        && y <= item.getAbsoluteTop() + item.getOffsetHeight()) {
        return item;
    }
    return null;
}

答案 1 :(得分:1)

您可以使用专用的重载TreeItem:

public class MyTreeItem extends TreeItem implements ContextMenuHandler {


    public SBTreeItem(SBItemTree tree, String name) {
        super();
        Label w = new Label(name);
        w.addDomHandler(this, ContextMenuEvent.getType());
        setWidget(w);
    }

            public void onContextMenu(ContextMenuEvent event) {
        Window.alert(getSBItem().getName());
        event.getNativeEvent().stopPropagation();

    }

   }

答案 2 :(得分:0)

答案 3 :(得分:0)

我知道这是一个老问题,但希望这是一个答案,可以节省群众从Google搜索中搜索此页面的时间。 IMO,最好的方法是使用谷歌自己的内部树搜索代码 - 这是一个可以很好地扩展树中元素数量的解决方案。一世 我正在使用GWT 2.5.1。

private void initTree() {
    tree = new Tree() {

        @Override
        public void onBrowserEvent(Event event) {
            /*
             * If the event is a context menu event, we want the tree item
             * to also be selected.
             * 
             * This logic must occur before the call to the superclass
             * method so the selection is updated before the context menu
             * logic executes. This is useful when we want to make items in
             * the context menu invisible/disabled based on the selection.
             */
            if (DOM.eventGetType(event) == Event.ONCONTEXTMENU) {
                if (getItemCount() > 0) {
                    // In my use case there is only 1 top-level tree item
                    TreeItem root = getItem(0);

                    // Taken from com.google.gwt.user.client.ui.Tree.elementClicked(Element):
                    ArrayList<Element> chain = new ArrayList<Element>();
                    collectElementChain(chain, getElement(), DOM.eventGetTarget(event));

                    TreeItem selection = findItemByChain(chain, 0, root);

                    /*
                     * For some reason SelectionEvent will only fire if
                     * selection is non-null; I am firing the selection
                     * event manually because I want to know when there has
                     * been a deselection of an item in the tree.
                     */
                    if (selection != null) {
                        this.setSelectedItem(selection);
                    } else {
                        SelectionEvent.fire(this, null);
                    }
                }
            }

            super.onBrowserEvent(event);
        }

    };

    tree.setAnimationEnabled(true);
}


//// BEGIN code copied from com.google.gwt.user.client.ui.Tree:

/**
 * Collects parents going up the element tree, terminated at the tree root.
 */
private void collectElementChain(ArrayList<Element> chain, Element hRoot,
        Element hElem) {
    if ((hElem == null) || (hElem == hRoot)) {
        return;
    }

    collectElementChain(chain, hRoot, DOM.getParent(hElem));
    chain.add(hElem);
}

private TreeItem findItemByChain(ArrayList<Element> chain, int idx,
        TreeItem root) {
    if (idx == chain.size()) {
        return root;
    }

    Element hCurElem = chain.get(idx);
    for (int i = 0, n = root.getChildCount(); i < n; ++i) {
        TreeItem child = root.getChild(i);
        if (child.getElement() == hCurElem) {
            TreeItem retItem = findItemByChain(chain, idx + 1,
                    root.getChild(i));
            if (retItem == null) {
                return child;
            }
            return retItem;
        }
    }

    return findItemByChain(chain, idx + 1, root);
}

//// END