简体   繁体   English

右键单击Java JTree的上下文菜单?

[英]Right-click context menu for Java JTree?

I'm trying to implement pop-up menus in Java JTree. 我正在尝试在Java JTree中实现弹出菜单。 I've sub-classed DefaultTreeCellRenderer (to change node appearance) and DefaultTreeCellEditor (to create Components to attach event listeners to, since apparently the Components that DefaultTreeCellRenderer.getTreeCellRendererComponent() returns can't do it?). 我已经对DefaultTreeCellRenderer(更改节点外观)和DefaultTreeCellEditor(创建组件以附加事件侦听器)进行了分类,因为显然DefaultTreeCellRenderer.getTreeCellRendererComponent()返回的组件不能这样做吗?)。 I don't really want to "edit" the nodes, just be able to pop-up a menu when a node gets right-clicked, but this is the only way I can think of doing it right now... 我真的不想“编辑”节点,只需在节点右键单击时弹出菜单,但这是我现在想到的唯一方法......

Below is the code that I have so far-- I'm just trying to figure out how to capture MouseEvents. 下面是我到目前为止的代码 - 我只想弄清楚如何捕获MouseEvents。 It sort of works, but badly. 它有点工作,但很糟糕。 What's a better way to accomplish what I'm trying to do here? 有什么更好的方法来完成我在这里要做的事情?

private class My_TreeCellRenderer extends DefaultTreeCellRenderer { 
    My_TreeCellRenderer() {
        super ();
    }   

    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);

        // set label text and tool tips
        setText(((My_Object)value).getTreeLabel());
        setToolTipText(((My_Object)value).getTreeToolTip());

        return this;
    }
}

private class My_TreeCellEditor extends DefaultTreeCellEditor { 
    private MouseAdapter ma;

    My_TreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
        super (tree, renderer);
        ma = new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    System.out.println("My Popup");
                }
            }
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    System.out.println("My Popup");
                }
            }
        };
    }

    public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
        String src_filename = null;

        // return non-editing component
        Component c = renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, true);

        // add mouse listener if it's not listening already
        MouseListener mouseListeners[] = c.getMouseListeners();
        int i;
        for (i=0; i < mouseListeners.length && mouseListeners[i] != ma; i++);
        if (i >= mouseListeners.length)
            c.addMouseListener(ma);

        return c;
    }

    protected boolean canEditImmediately(EventObject event) {
        if (event instanceof MouseEvent && ((MouseEvent)event).getClickCount() == 1)
            return true;
        else
            return false;
    }
}

This task is simple to accomplish, the following is all you need: 这个任务很容易完成,以下是您所需要的:

//create a class which implements the MouseListener interface and
//implement the following in your overridden mouseClicked method

@Override
public void mouseClicked(MouseEvent e) {

    if (SwingUtilities.isRightMouseButton(e)) {

        int row = tree.getClosestRowForLocation(e.getX(), e.getY());
        tree.setSelectionRow(row);
        popupMenu.show(e.getComponent(), e.getX(), e.getY());
    }
}

You can then add this custom listener to your desired tree(s). 然后,您可以将此自定义侦听器添加到所需的树。

Taken right out of the JTree API 取自JTree API

 // If you are interested in detecting either double-click events or when a user clicks on a node, regardless of whether or not it was selected, we recommend you do the following:

 final JTree tree = ...;

 MouseListener ml = new MouseAdapter() {
     public void mousePressed(MouseEvent e) {
         int selRow = tree.getRowForLocation(e.getX(), e.getY());
         TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
         if(selRow != -1) {
             if(e.getClickCount() == 1) {
                 mySingleClick(selRow, selPath);
             }
             else if(e.getClickCount() == 2) {
                 myDoubleClick(selRow, selPath);
             }
         }
     }
 };
 tree.addMouseListener(ml);

Of course you need to modify it a bit for right click instead of left click 当然,您需要稍微修改它以进行右键单击而不是左键单击

Thanks everyone. 感谢大家。 I knew something was wrong when I was spending that much effort on implementing a simple popup. 当我花费大量精力实现一个简单的弹出窗口时,我知道出了什么问题。

I dismissed this line of thought at first because it felt weird to resort to x- and y- coordinates to find the node I'm looking for, but I guess this is the way to do it. 我首先驳回了这一思路,因为使用x和y坐标找到我正在寻找的节点感觉很奇怪,但我想这是做到这一点的方法。

    // add MouseListener to tree
    MouseAdapter ma = new MouseAdapter() {
        private void myPopupEvent(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            JTree tree = (JTree)e.getSource();
            TreePath path = tree.getPathForLocation(x, y);
            if (path == null)
                return; 

            tree.setSelectionPath(path);

            My_Obj obj = (My_Obj)path.getLastPathComponent();

            String label = "popup: " + obj.getTreeLabel();
            JPopupMenu popup = new JPopupMenu();
            popup.add(new JMenuItem(label));
            popup.show(tree, x, y);
        }
        public void mousePressed(MouseEvent e) {
            if (e.isPopupTrigger()) myPopupEvent(e);
        }
        public void mouseReleased(MouseEvent e) {
            if (e.isPopupTrigger()) myPopupEvent(e);
        }
    };

    (...)

    JTree tree = new JTree();
    tree.addMouseListener(ma);

I think you're making things way harder than they need to be. 我认为你的做法比他们需要的更难。
JTree has several "add_foo_Listener" methods on it. JTree上有几个“add_foo_Listener”方法。 Implement one of those (TreeSelectionListener looks about right), and then you've got the currently selected node. 实现其中一个(TreeSelectionListener看起来正确),然后你有了当前选择的节点。
Implement a MouseListener so that you can detect the right-click event (and add it to the JTree, since JTree's a Component), and then you should have everything you need to post a context-sensitive menu. 实现一个MouseListener,以便您可以检测到右键单击事件(并将其添加到JTree,因为JTree是一个组件),然后您应该拥有发布上下文相关菜单所需的一切。
Check out this tutorial for more details. 有关更多详细信息,请查看本教程

The Renderer is only a transient "rubber stamp", so adding an input listener on that wont be particularly helpful. 渲染器只是一个短暂的“橡皮图章”,因此添加输入监听器不会特别有用。 The Editor, as you point out, is only there once you have gestured to edit. 正如你所指出的那样,编辑只有在你打手势编辑之后才会出现。 So you want to add a listener to the JTree (assuming it isn't implemented as a composite component). 所以你想为JTree添加一个监听器(假设它没有实现为复合组件)。

Call addRightClickListener() to add the right-click context menu listener to your JTree . 调用addRightClickListener()以将右键单击上下文菜单侦听器添加到JTree Both overrides are for proper cross-platform functionality ( Windows and Linux differ here). 这两个覆盖都是为了适当的跨平台功能( WindowsLinux在这里不同)。

private void addRightClickListener()
{
    MouseListener mouseListener = new MouseAdapter()
    {
        @Override
        public void mousePressed(MouseEvent mouseEvent)
        {
            handleContextMenu(mouseEvent);
        }

        @Override
        public void mouseReleased(MouseEvent mouseEvent)
        {
            handleContextMenu(mouseEvent);
        }
    };

    tree.addMouseListener(mouseListener);
}

private void handleContextMenu(MouseEvent mouseEvent)
{
    if (mouseEvent.isPopupTrigger())
    {
        MyContextMenu contextMenu = new MyContextMenu();

        contextMenu.show(mouseEvent.getComponent(),
                mouseEvent.getX(),
                mouseEvent.getY());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM