Réponses:
Vous appelez probablement manuellement setVisible(true)
sur le menu. Cela peut provoquer un comportement de buggy désagréable dans le menu.
La show(Component, int x, int x)
méthode gère toutes les choses dont vous avez besoin (surligner les choses au survol de la souris et fermer la fenêtre contextuelle si nécessaire) où l'utilisation setVisible(true)
montre simplement le menu sans ajouter de comportement supplémentaire.
Pour créer un menu contextuel clic droit, créez simplement un fichier JPopupMenu
.
class PopUpDemo extends JPopupMenu {
JMenuItem anItem;
public PopUpDemo() {
anItem = new JMenuItem("Click Me!");
add(anItem);
}
}
Ensuite, tout ce que vous avez à faire est d'ajouter une personnalisation MouseListener
aux composants pour lesquels vous souhaitez que le menu apparaisse.
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 un peu plus approfondie .
Remarque: Si vous remarquez que le menu contextuel apparaît loin de l'endroit où l'utilisateur a cliqué, essayez d'utiliser les méthodes e.getXOnScreen()
et e.getYOnScreen()
pour les coordonnées x et y.
PopClickListener
extension s'étend MouseAdapter
?
component
?
Cette question est un peu ancienne - tout comme les réponses (et le tutoriel aussi)
L'API actuelle pour définir un menu contextuel dans Swing est
myComponent.setComponentPopupMenu(myPopupMenu);
De cette façon, il sera affiché automatiquement, à la fois pour les déclencheurs de souris et de clavier (ce dernier dépend de LAF). De plus, il prend en charge la réutilisation du même popup sur les enfants d'un conteneur. Pour activer cette fonctionnalité:
myChild.setInheritsPopupMenu(true);
JTable
pour qu'il apparaisse sur la ligne sélectionnée ou sur la ligne où vous faites un clic droit? Ou dans ce scénario, l'ancienne méthode est-elle celle à choisir?
Il existe une section sur la création d'un menu contextuel dans l'article Comment utiliser les menus des didacticiels Java qui explique comment utiliser la JPopupMenu
classe.
L'exemple de code dans le didacticiel montre comment ajouter des MouseListener
s 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 façon d'afficher un menu contextuel sur un composant.)
Le code suivant implémente un menu contextuel par défaut connu à partir des fonctions Windows
de copier, couper, coller, sélectionner tout, annuler et rétablir. Cela fonctionne également sur 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;
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);
}
}
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.
releasedEvent.isPopupTrigger()
au lieu de releasedEvent.getButton() == MouseEvent.BUTTON3
pour fonctionner correctement sur toutes les plateformes.
pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
ceux - ci doivent être les deux Ex
ou non Ex
. La Ex
version de getMenuShortcutKeyMask()
n'est disponible que depuis java 10+.
Je corrigerai l'utilisation de cette méthode suggérée par @BullyWillPlaza. La raison en est que lorsque j'essaie d'ajouter ajouter textArea uniquement à contextMenu, ce n'est pas visible, et si je l'ajoute à la fois à contextMenu et à certains panneaux, il compte: une double association parent différente si j'essaie de passer à l'éditeur de conception.
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 l'objet texte sur lequel vous devez avoir une fenêtre contextuelle. Ce que cela fera, c'est que lorsque vous cliquez avec le bouton droit sur votre objet texte, il ajoutera cette fenêtre contextuelle et l'affichera. De cette façon, vous ne rencontrez pas cette erreur. La solution créée par @BullyWillPlaza est très bonne, riche et rapide à implémenter dans votre programme, vous devriez donc l'essayer pour voir comment vous l'aimez.