Comment créer un menu contextuel avec clic droit dans Java Swing?

Je suis en train de créer un menu contextuel en JMenu le bouton droit de la souris en instanciant un nouveau JMenu par clic droit et en définissant son emplacement à la position de la souris. Y a-t-il une meilleure façon?

Vous appelez probablement manuellement setVisible(true) dans le menu. Cela peut causer de mauvais comportements dans le menu.

La méthode show(Component, int x, int x) gère tout ce qui doit se passer (mise en surbrillance des éléments au survol et fermeture de la fenêtre si nécessaire) où l’utilisation de setVisible(true) montre simplement le menu sans append de comportement.

Pour créer un menu contextuel avec clic droit, créez simplement un JPopupMenu .

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

Ensuite, il vous suffit d’append un MouseListener personnalisé aux composants que vous souhaitez MouseListener dans le menu.

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

Bien sûr, les tutoriels ont une explication légèrement plus approfondie .

Remarque: Si vous remarquez que le menu contextuel apparaît à un endroit où l’utilisateur a cliqué, essayez d’utiliser les e.getXOnScreen() et e.getYOnScreen() pour les coordonnées x et y.

Cette question est un peu ancienne – tout comme les réponses (et le tutoriel également)

L’api actuel pour configurer un popupMenu dans Swing est

 myComponent.setComponentPopupMenu(myPopupMenu); 

De cette façon, il sera affiché automatiquement, à la fois pour les déclencheurs de la souris et du clavier (ce dernier dépend de LAF). De plus, il prend en charge la réutilisation du même popup dans les enfants d’un conteneur. Pour activer cette fonctionnalité:

 myChild.setInheritsPopupMenu(true); 

Il y a une section sur l’ affichage d’un menu contextuel dans l’article Comment utiliser les menus de Java Tutorials, qui explique comment utiliser la classe JPopupMenu .

L’exemple de code dans le didacticiel montre comment append MouseListener aux composants qui doivent afficher un menu contextuel et affiche le menu en conséquence.

(La méthode que vous décrivez est assez similaire à la façon dont le didacticiel présente la manière d’afficher un menu contextuel sur un composant.)

Le code suivant implémente un menu contextuel par défaut connu sous Windows avec les fonctions copier, couper, coller, sélectionner tout, annuler et rétablir. Il fonctionne également sous Linux et 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; Ssortingng selectedText = textComponent.getSelectedText(); Ssortingng 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.ssortingngFlavor) && 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); } } 

Usage:

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

Maintenant, le textArea aura un menu contextuel quand il sera cliqué avec le bouton droit de la souris.

Je vais corriger l’utilisation de la méthode suggérée par @BullyWillPlaza. La raison en est que lorsque j’essaie d’append add textArea à seulement contextMenu, il n’est pas visible et si je l’ajoute à contextMenu et à un autre panneau, il est compatible avec:

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

Créez un écouteur de souris comme celui-ci pour les objects texte dont vous avez besoin d’avoir une fenêtre contextuelle. Qu’est-ce que cela va faire est lorsque vous cliquez avec le bouton droit sur votre object texte, il va alors append cette popup et l’afficher. De cette façon, vous ne rencontrez pas cette erreur. La solution faite par @BullyWillPlaza est très bonne, riche et rapide à implémenter dans votre programme, vous devriez donc l’essayer, voir comment vous l’aimez.