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

我正在尝试在Java JTree中实现弹出菜单。 我已经对DefaultTreeCellRenderer(更改节点外观)和DefaultTreeCellEditor(创建组件以附加事件侦听器)进行了分类,因为显然DefaultTreeCellRenderer.getTreeCellRendererComponent()返回的组件不能这样做吗?)。 我真的不想“编辑”节点,只需在节点右键单击时弹出菜单,但这是我现在想到的唯一方法……

下面是我到目前为止的代码 – 我只想弄清楚如何捕获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) c.addMouseListener(ma); return c; } protected boolean canEditImmediately(EventObject event) { if (event instanceof MouseEvent && ((MouseEvent)event).getClickCount() == 1) return true; else return false; } } 

这个任务很容易完成,以下是您所需要的:

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

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

取自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); 

当然,你需要修改一下右键而不是左键单击

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

我首先驳回了这一思路,因为使用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); 

我认为你做的事情比他们需要的更难。
JTree上有几个“add_foo_Listener”方法。 实现其中一个(TreeSelectionListener看起来正确),然后你有了当前选择的节点。
实现一个MouseListener,以便您可以检测到右键单击事件(并将其添加到JTree,因为JTree是一个组件),然后您应该拥有发布上下文相关菜单所需的一切。
有关更多详细信息,请查看本教程 。

渲染器只是一个短暂的“橡皮图章”,因此添加输入监听器不会特别有用。 正如你所指出的那样,编辑只有在你打手势编辑之后才会出现。 所以你想为JTree添加一个监听器(假设它没有实现为复合组件)。

调用addRightClickListener()以将右键单击上下文菜单侦听器添加到JTree 。 这两个覆盖都是为了适当的跨平台function( 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()); } }