右键单击JavaJTree的上下文菜单?

右键单击JavaJTree的上下文菜单?,java,contextmenu,jtree,Java,Contextmenu,Jtree,我试图在JavaJTree中实现弹出菜单。我对DefaultTreeCellRenderer(更改节点外观)和DefaultTreeCellEditor(创建要将事件侦听器附加到的组件)进行了子分类,因为DefaultTreeCellRenderer.GetTreeCellRenderComponent()返回的组件显然无法执行此操作。我真的不想“编辑”节点,只是能够在右键单击节点时弹出菜单,但这是我现在唯一能想到的方法 下面是我到目前为止的代码——我只是想弄清楚如何捕获MouseEvents。

我试图在JavaJTree中实现弹出菜单。我对DefaultTreeCellRenderer(更改节点外观)和DefaultTreeCellEditor(创建要将事件侦听器附加到的组件)进行了子分类,因为DefaultTreeCellRenderer.GetTreeCellRenderComponent()返回的组件显然无法执行此操作。我真的不想“编辑”节点,只是能够在右键单击节点时弹出菜单,但这是我现在唯一能想到的方法

下面是我到目前为止的代码——我只是想弄清楚如何捕获MouseEvents。这有点管用,但很糟糕。有什么更好的方法来完成我在这里要做的事情

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;
    }
}
私有类My_TreeCellRenderer扩展了DefaultTreeCellRenderer{
My_TreeCellRenderer(){
超级();
}   
公共组件GetTreeCellRenderComponent(JTree树、对象值、布尔选定、布尔展开、布尔叶、int行、布尔hasFocus){
getTreeCellRenderComponent(树、值、选定、展开、叶、行、hasFocus);
//设置标签文本和工具提示
setText(((我的对象)值).getTreeLabel();
setToolTipText(((我的对象)值).getTreeToolTip();
归还这个;
}
}
私有类My_TreeCellEditor扩展了DefaultTreeCellEditor{
私人MouseAdapter ma;
My_TreeCellEditor(JTree树,DefaultTreeCellRenderer){
超级(树,渲染器);
ma=新的MouseAdapter(){
公共无效鼠标按下(MouseEvent e){
如果(如isPopupTrigger()){
System.out.println(“我的弹出窗口”);
}
}
公共无效MouseEvent(MouseEvent e){
如果(如isPopupTrigger()){
System.out.println(“我的弹出窗口”);
}
}
};
}
公共组件getTreeCellEditorComponent(JTree树,对象值,布尔选定,布尔展开,布尔叶,int行){
字符串src_filename=null;
//返回非编辑组件
Component c=renderer.GetTreeCellrenderComponent(树、值、选定、展开、叶、行、真);
//如果鼠标侦听器尚未侦听,请添加鼠标侦听器
MouseListener mouseListeners[]=c.getMouseListeners();
int i;
对于(i=0;i=mouseListeners.length)
c、 addMouseListener(硕士);
返回c;
}
立即受保护的布尔值(EventObject事件){
if(MouseEvent的事件实例&((MouseEvent)事件)。getClickCount()==1)
返回true;
其他的
返回false;
}
}

渲染器只是一个暂时的“橡皮图章”,因此在其上添加一个输入侦听器不会特别有用。正如您所指出的,只有在您做出编辑手势后,编辑器才会出现。因此,您希望将侦听器添加到JTree(假设它不是作为复合组件实现的)。

直接从


当然,你需要修改一下鼠标右键而不是左键,我认为你让事情变得比实际情况更困难了。
JTree上有几个“add\u foo\u Listener”方法。实现其中一个(TreeSelectionListener看起来很右),然后就得到了当前选定的节点
实现一个MouseListener,这样您就可以检测右键单击事件(并将其添加到JTree,因为JTree是一个组件),然后您就应该拥有发布上下文相关菜单所需的一切。

请查看此文件以了解更多详细信息。

谢谢大家。当我花费那么多精力实现一个简单的弹出窗口时,我知道出了问题

我一开始就放弃了这种想法,因为使用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);

此任务很容易完成,以下是您所需的全部内容:

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

然后,您可以将此自定义侦听器添加到所需的树中。

调用
addRightClickListener()
将右键单击上下文菜单侦听器添加到
JTree
。这两种覆盖都是为了实现正确的跨平台功能(
Windows
Linux
在这里有所不同)


您每次都在创建一个JPOppMenu。将创建移动到其他地方,只有在事件上修改它时才进行创建。这是过早优化()的一个很好的例子。除非有理由这样做(例如,缓慢的资源初始化),否则创建长期存在的对象是没有意义的。
//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());
    }
}
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());
    }
}