如何在Java Swing中创build右键单击上下文菜单?

我目前正在创build一个右键单击上下文菜单通过实例化一个新的JMenu右键单击并将其位置设置为鼠标的位置…有没有更好的方法?

您可能手动调用菜单上的setVisible(true) 。 这可能会导致在菜单中的一些讨厌的马车行为。

show(Component, int x, int x)方法处理所有需要发生的事情(在必要时突出显示鼠标hover的事件并closurespopup窗口),其中使用setVisible(true)只显示菜单而不添加任何其他行为。

要创build一个右键单击popup菜单只需创build一个JPopupMenu

 class PopUpDemo extends JPopupMenu { JMenuItem anItem; public PopUpDemo(){ anItem = new JMenuItem("Click Me!"); add(anItem); } } 

然后,您只需将自定义的MouseListener添加到想要popup菜单的组件中。

 class PopClickListener extends MouseAdapter { public void mousePressed(MouseEvent e){ if (e.isPopupTrigger()) doPop(e); } public void mouseReleased(MouseEvent e){ if (e.isPopupTrigger()) doPop(e); } private void doPop(MouseEvent e){ PopUpDemo menu = new PopUpDemo(); menu.show(e.getComponent(), e.getX(), e.getY()); } } // Then on your component(s) component.addMouseListener(new PopClickListener()); 

当然,这些教程有一个更深入的解释。

注意:如果您注意到popup式菜单出现在用户点击的地方,请尝试使用e.getXOnScreen()e.getYOnScreen()方法获取x和y坐标。

这个问题有点老了 – 答案(以及教程)也是如此,

当前在Swing中设置popupMenu的api是

 myComponent.setComponentPopupMenu(myPopupMenu); 

这样,它将自动显示,鼠标和键盘触发器(后者取决于LAF)。 另外,它支持在容器的子项中重复使用相同的popup窗口。 要启用该function:

 myChild.setInheritsPopupMenu(true); 

在“Java教程 ”的“ 如何使用菜单”一文中,介绍了如何使用JPopupMenu类来创buildpopup式菜单 。

本教程中的示例代码演示了如何将MouseListener添加到应显示popup菜单的组件,并相应地显示菜单。

(您所描述的方法与本教程介绍在组件上显示popup式菜单的方式非常相似。)

以下代码通过复制,剪切,粘贴,全选,撤销和重做function实现了Windows默认的上下文菜单。 它也适用于LinuxMac OS X

 import javax.swing.*; import javax.swing.text.JTextComponent; import javax.swing.undo.UndoManager; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class DefaultContextMenu extends JPopupMenu { private Clipboard clipboard; private UndoManager undoManager; private JMenuItem undo; private JMenuItem redo; private JMenuItem cut; private JMenuItem copy; private JMenuItem paste; private JMenuItem delete; private JMenuItem selectAll; private JTextComponent textComponent; public DefaultContextMenu() { undoManager = new UndoManager(); clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); addPopupMenuItems(); } private void addPopupMenuItems() { undo = new JMenuItem("Undo"); undo.setEnabled(false); undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); undo.addActionListener(event -> undoManager.undo()); add(undo); redo = new JMenuItem("Redo"); redo.setEnabled(false); redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); redo.addActionListener(event -> undoManager.redo()); add(redo); add(new JSeparator()); cut = new JMenuItem("Cut"); cut.setEnabled(false); cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); cut.addActionListener(event -> textComponent.cut()); add(cut); copy = new JMenuItem("Copy"); copy.setEnabled(false); copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); copy.addActionListener(event -> textComponent.copy()); add(copy); paste = new JMenuItem("Paste"); paste.setEnabled(false); paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); paste.addActionListener(event -> textComponent.paste()); add(paste); delete = new JMenuItem("Delete"); delete.setEnabled(false); delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); delete.addActionListener(event -> textComponent.replaceSelection("")); add(delete); add(new JSeparator()); selectAll = new JMenuItem("Select All"); selectAll.setEnabled(false); selectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); selectAll.addActionListener(event -> textComponent.selectAll()); add(selectAll); } private void addTo(JTextComponent textComponent) { textComponent.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent pressedEvent) { if ((pressedEvent.getKeyCode() == KeyEvent.VK_Z) && ((pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0)) { if (undoManager.canUndo()) { undoManager.undo(); } } if ((pressedEvent.getKeyCode() == KeyEvent.VK_Y) && ((pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0)) { if (undoManager.canRedo()) { undoManager.redo(); } } } }); textComponent.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent releasedEvent) { handleContextMenu(releasedEvent); } @Override public void mouseReleased(MouseEvent releasedEvent) { handleContextMenu(releasedEvent); } }); textComponent.getDocument().addUndoableEditListener(event -> undoManager.addEdit(event.getEdit())); } private void handleContextMenu(MouseEvent releasedEvent) { if (releasedEvent.getButton() == MouseEvent.BUTTON3) { processClick(releasedEvent); } } private void processClick(MouseEvent event) { textComponent = (JTextComponent) event.getSource(); textComponent.requestFocus(); boolean enableUndo = undoManager.canUndo(); boolean enableRedo = undoManager.canRedo(); boolean enableCut = false; boolean enableCopy = false; boolean enablePaste = false; boolean enableDelete = false; boolean enableSelectAll = false; String selectedText = textComponent.getSelectedText(); String text = textComponent.getText(); if (text != null) { if (text.length() > 0) { enableSelectAll = true; } } if (selectedText != null) { if (selectedText.length() > 0) { enableCut = true; enableCopy = true; enableDelete = true; } } if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor) && textComponent.isEnabled()) { enablePaste = true; } undo.setEnabled(enableUndo); redo.setEnabled(enableRedo); cut.setEnabled(enableCut); copy.setEnabled(enableCopy); paste.setEnabled(enablePaste); delete.setEnabled(enableDelete); selectAll.setEnabled(enableSelectAll); // Shows the popup menu show(textComponent, event.getX(), event.getY()); } public static void addDefaultContextMenu(JTextComponent component) { DefaultContextMenu defaultContextMenu = new DefaultContextMenu(); defaultContextMenu.addTo(component); } } 

用法:

 JTextArea textArea = new JTextArea(); DefaultContextMenu.addDefaultContextMenu(textArea); 

现在textArea右键单击时会有一个上下文菜单。

我将更正@BullyWillPlazabuild议的那种方法的用法。 原因是,当我尝试添加textArea只contextMenu它是不可见的,如果我将它添加到两个contextMenu和一些面板它ecounters:不同的父双关联,如果我尝试切换到devise编辑器。

 TexetObjcet.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)){ contextmenu.add(TexetObjcet); contextmenu.show(TexetObjcet, 0, 0); } } }); 

使鼠标监听器像这样的文本对象,你需要popup。 这将做什么是当你右键单击文本对象,然后将添加该popup并显示它。 这样你就不会遇到这个错误。 @BullyWillPlaza制作的解决scheme非常好,丰富且快速,可以在您的程序中实现,所以您应该尝试一下,看看您是否喜欢它。