Como faço para criar um menu de contexto do botão direito no Java Swing?

Eu estou atualmente criando um menu de contexto do botão direito do mouse, instanciando um novo JMenu no botão direito e definindo sua localização para a posição do mouse … Existe uma maneira melhor?

Você provavelmente está chamando manualmente setVisible(true) no menu. Isso pode causar algum comportamento desagradável de bugs no menu.

O método show(Component, int x, int x) manipula todas as coisas que você precisa para acontecer, (destacando coisas ao passar o mouse e fechando o popup quando necessário) onde usar setVisible(true) apenas mostra o menu sem adicionar nenhum comportamento adicional.

Para fazer um clique direito do menu, basta criar um JPopupMenu .

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

Então, tudo o que você precisa fazer é adicionar um MouseListener personalizado aos componentes para os quais deseja que o menu seja exibido.

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

Claro, os tutoriais têm uma explicação um pouco mais aprofundada .

Nota: Se você perceber que o menu pop-up está aparecendo muito longe de onde o usuário clicou, tente usar os e.getXOnScreen() e e.getYOnScreen() para as coordenadas x e y.

Esta questão é um pouco antiga – assim como as respostas (e o tutorial também)

A API atual para configurar um popupMenu no Swing é

 myComponent.setComponentPopupMenu(myPopupMenu); 

Desta forma, será mostrado automagicamente, tanto para gatilhos de mouse e teclado (este último depende do LAF). Além disso, ele suporta a reutilização do mesmo pop-up nos filhos de um contêiner. Para ativar esse recurso:

 myChild.setInheritsPopupMenu(true); 

Há uma seção sobre Como criar um menu pop-up no artigo Como usar menus do The Java Tutorials, que explica como usar a class JPopupMenu .

O código de exemplo no tutorial mostra como adicionar MouseListener s aos componentes que devem exibir um menu pop-up e exibe o menu de acordo.

(O método que você descreve é ​​bastante semelhante ao modo como o tutorial apresenta a maneira de mostrar um menu pop-up em um componente.)

O código a seguir implementa um menu de contexto padrão conhecido do Windows com as funções copiar, cortar, colar, selecionar tudo, desfazer e refazer. Também funciona no Linux e no Mac 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); } } 

Uso:

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

Agora o textArea terá um menu de contexto quando ele for clicado com o botão direito do mouse.

Vou corrigir o uso desse método que o @BullyWillPlaza sugeriu. Razão é que quando eu tento adicionar add textArea apenas para contextMenu não é visível, e se eu adicioná-lo tanto para contextMenu e algum painel ecounters: Diferente associação dupla pai se eu tentar mudar para o editor de design.

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

Faça ouvinte do mouse como este para o object de texto que você precisa ter pop-up. O que isso vai fazer é quando você clica com o botão direito do mouse no seu object de texto, ele adicionará esse pop-up e o exibirá. Desta forma, você não encontrará esse erro. A solução que o @BullyWillPlaza criou é muito boa, rica e rápida de implementar em seu programa, então você deve tentar ver como você gosta.

Intereting Posts