GWT:右键单击选择一个 TreeItem

发布于 2024-08-29 20:08:00 字数 507 浏览 2 评论 0原文

我正在捕获右键单击事件以显示上下文菜单。我无法弄清楚的是,在显示上下文菜单之前,如何通过右键单击实际选择 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);
  }

 };

I'm capturing a right click event to show a context menu. What I haven't been able to figure out, is how to make the right click actually select the TreeItem, prior to showing of context menu.

All help is appreciated.

 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);
  }

 };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

太阳公公是暖光 2024-09-05 20:08:00

ONMOUSEDOWN 事件在 ONCONTEXTMENU 之前触发。您是否尝试过监听 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;
}

ONMOUSEDOWN event gets fired before ONCONTEXTMENU. Have you tried to listen for onMouseDown events, and set the selected item? Something along these lines:

@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;
    }

and findSelectedItem traverses the tree looking for the selected item:

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;
}
桃扇骨 2024-09-05 20:08:00

您可以使用专用的重载 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();

    }

   }

You can use dedicated overloaded 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();

    }

   }
深海夜未眠 2024-09-05 20:08:00

我知道这是一个老问题,但希望这里有一个答案,可以为通过 Google 搜索访问此页面的大众节省时间。 IMO,最好的方法是使用 Google 自己的内部树搜索代码 - 这是一个可以很好地根据树中元素数量进行扩展的解决方案。我
我正在使用 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

I know this is an old question, but hopefully here's an answer that will save time for the masses hitting this page from a Google search. IMO, the best way is to use Google's own internal tree searching code -- it's a solution that scales very well with the number of elements in the tree. I
am using 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文