Java SWT 树菜单仅显示一级树

Java SWT Tree Menu Shown only for one level of the tree

我正在制作一个使用 java SWT 树结构的程序。这棵树是建立在从外部文件和用户输入中读取的数据之上的。 对于这棵树,我还附加了一个右键单击菜单。

主要问题是这棵树的菜单遍及他的所有项目,我希望它只在某个级别显示。

我还想为不同的树级别设置不同的菜单或菜单选项。

树的所有创建都在一个函数中:

public void createTree(final Composite container){
    try{
        for(Object element : container.getChildren()){
            if(element instanceof Tree){
                ((Tree) element).dispose();
            }
        }
        // function to verify if the tree is still in my container composite, and if so, I'll dispose the tree, because I am going to construct a new one

        final Tree variantTree = new Tree(container, SWT.CHECK | SWT.V_SCROLL | SWT.H_SCROLL);//creating new tree object
        variantTree.setBounds(10, 65, 400, 400);//dimensions
        //variantTree.setData("variant"); -- wanted to abuse this method to make a difference between the tree's level, 
             //but this attribute is shared across all the tree, and I cannot make a distinction between my levels

        if(..){
            //here I am using the data saved in a tree data structure to populate my SWT Tree
        }

        variantTree.addListener(SWT.Selection, new Listener(){
            //this is a listener used for the tree's checkboxes, using them to select different items from my tree
        });

        final Menu treeMenu = new Menu(variantTree);
        variantTree.setMenu(treeMenu);//adding the right click menu

        treeMenu.addMenuListener(new MenuAdapter(){
            //the menu's items are declared here: the buttons that I want to have and the their listeners
            //i am disposing the menu's items if there are any

                MenuItem newItem = new MenuItem(treeMenu, SWT.NONE);
                newItem.setText("new button...  ");
                newItem.addListener(SWT.Selection, new Listener(){

                    @Override
                    public void handleEvent(Event event) {
                            String item = variantTree.getSelection()[0].getText();//can I use this to make different menus for different tree levels?
                            for(Node element : TestControl.getTree().getChildren()){//getting the tree data structure that I have saved in a static way via a class
                                if(element.getName().equals(item)){
                            //opening a file dialog here and doing some operations
                            }
                      }
                });
        });

        //this is where I want to make the distinction between the levels of the tree, such as that I will have this menu show up only for the root of my tree, or the first level of the tree, since I will have multiple trees
        variantTree.addMenuDetectListener(new MenuDetectListener(){

            @Override
            public void menuDetected(MenuDetectEvent event) {
                // TODO Auto-generated method stub
                if(/*condition*/){ //I messed around with the tree's methods and attributes, nothing so far has come in handy to help me make a distinction between my tree's levels
                    event.doit = true;
                    //System.out.println(variantTree.getSelectionCount()); --I don't know if this can help me either, I tried to see if this will return differently for every level of the tree, but the return values is always 0
                    //find some kind of handle
                }else{
                    event.doit = false;
                }
            }

        });

另外,我想在树的第二层显示另一个菜单,我可以使用 String item = variantTree.getSelection()[0].getText();,以某种方式修改以满足我的需要吗?比方说,String item = variantTree.getSelection()[1].getText(); 为第二级?

我的 SWT 树的每个根的最大深度为 3,它看起来像这样:

root1 - 只想要这个项目的菜单
|---儿童 - 1级
|------儿童 - 2 级

root2 - 只想要这个项目的菜单
|---儿童 - 1级
|--------儿童 - 2 级

谢谢。

我已经通过以下方式解决了我的问题。 如果你真的看到我的代码,有以下几行:

for(Node element : TestControl.getTree().getChildren()){//getting the tree data structure that I have saved in a static way via a class
   if(element.getName().equals(item)){
         //opening a file dialog here and doing some operations
   }
}

我正在获取我的树数据结构的第一层,然后我正在验证我的 SWT 树的根名称是否等于树数据结构的根。

使用相同的方法,这将导致 SWT 树的菜单侦听器结束:

variantTree.addMenuDetectListener(new MenuDetectListener(){

            @Override
            public void menuDetected(MenuDetectEvent event) {
                // TODO Auto-generated method stub
                for(Node element : TestControl.getTree().getChildren()){
                    if(variantTree.getSelection()[0].getText().equals(element.getName())){
                        event.doit = true;
                        break;//need this, because it will propagate only to the last item, or it will have a strange behaviour
                    }else{
                        event.doit = false;
                    }
                }
            }

        });

其中 element 是我的树数据结构中的一个节点。 希望对遇到同样问题的人有所帮助。

无需比较TreeItem 文本,只需检查项目的级别,例如检查它是否有 parent.

public static void main(String[] args)
{
    Display display = Display.getDefault();
    final Shell shell = new Shell(display);
    shell.setText("Whosebug");
    shell.setLayout(new FillLayout());

    final Tree tree = new Tree(shell, SWT.NONE);

    for (int i = 0; i < 10; i++)
    {
        TreeItem item = new TreeItem(tree, SWT.NONE);
        item.setText("Parent " + i);

        for (int j = 0; j < 3; j++)
        {
            TreeItem child = new TreeItem(item, SWT.NONE);
            child.setText("Child " + i + " " + j);

            for (int k = 0; k < 3; k++)
            {
                TreeItem grandChild = new TreeItem(child, SWT.NONE);
                grandChild.setText("Child " + i + " " + j + " " + k);
            }
        }
    }

    final Menu menu = new Menu(tree);
    tree.setMenu(menu);
    tree.addMenuDetectListener(new MenuDetectListener()
    {
        @Override
        public void menuDetected(MenuDetectEvent e)
        {
            TreeItem treeItem = tree.getSelection()[0];

            e.doit = getLevelOfItem(treeItem) < 2;
        }
    });
    menu.addMenuListener(new MenuAdapter()
    {
        public void menuShown(MenuEvent e)
        {
            TreeItem item = tree.getSelection()[0];

            setMenu(menu, item);
        }
    });

    shell.pack();
    shell.open();
    while (!shell.isDisposed())
    {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}

private static void setMenu(Menu menu, TreeItem item)
{
    int level = getLevelOfItem(item);

    MenuItem[] items = menu.getItems();
    for (MenuItem i : items)
    {
        i.dispose();
    }

    switch (level)
    {
        case 0:
            for(int i = 0; i < 2; i++)
            {
                MenuItem newItem = new MenuItem(menu, SWT.NONE);
                newItem.setText("Menu item " + i);
            }
            break;
        case 1:
            for(int i = 0; i < 4; i++)
            {
                MenuItem newItem = new MenuItem(menu, SWT.NONE);
                newItem.setText("Menu item " + i);
            }
            break;
    }
}

private static int getLevelOfItem(TreeItem item)
{
    int counter = 0;

    while(item.getParentItem() != null)
    {
        item = item.getParentItem();
        counter++;
    }

    return counter;
}

这将显示第 0 级和第 1 级的不同菜单,而不会显示第 2 级的菜单。