Je suis en train de créer un menu contextuel par clic-droit en instanciant un nouveau JMenu
en cliquant avec le bouton droit de la souris et en définissant son emplacement sur celui de la position de la souris ... Y a-t-il un meilleur moyen?Comment créer un menu contextuel avec un clic droit dans Java Swing?
Répondre
Vous probablement appelez manuellement setVisible(true)
dans le menu. Cela peut provoquer un comportement buggy méchant dans le menu. La méthode show(Component, int x, int x)
gère toutes les choses que vous devez faire, (en mettant en évidence les choses au survol de la souris et en fermant la fenêtre si nécessaire) où setVisible(true)
affiche simplement le menu sans ajouter de comportement supplémentaire.
Pour créer un menu contextuel avec le bouton droit de la souris, créez simplement JPopupMenu
.
class PopUpDemo extends JPopupMenu {
JMenuItem anItem;
public PopUpDemo(){
anItem = new JMenuItem("Click Me!");
add(anItem);
}
}
Ensuite, tout ce que vous devez faire est d'ajouter une mesure MouseListener
aux composants que vous souhaitez le menu contextuel de.
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 slightly more in-depth.
Note: Si vous remarquez que le menu contextuel apparaît loin de l'endroit où l'utilisateur a cliqué, essayez d'utiliser les méthodes et e.getXOnScreen()
e.getYOnScreen()
pour les coordonnées x et y.
Il ya une section sur Bringing Up a Popup Menu dans l'article How to Use Menus de The Java Tutorials qui explique comment utiliser la classe JPopupMenu
.
L'exemple de code du didacticiel montre comment ajouter MouseListener
aux composants devant 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 tutoriel présente la façon pour afficher un menu contextuel sur un composant.)
Cette question est un peu vieux - tout comme les réponses (et le tutoriel ainsi)
Le api actuel pour la fixation d'un popupMenu Swing est
myComponent.setComponentPopupMenu(myPopupMenu);
De cette façon, il sera affiché automagiquement , à 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 de la même fenêtre contextuelle sur les enfants d'un conteneur. Pour activer cette fonctionnalité:
myChild.setInheritsPopupMenu(true);
Le code suivant implémente un menu contextuel par défaut connu de Windows
avec copier, couper, coller, tout sélectionner, annuler et rétablir les fonctions. Il travaille é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);
}
}
Utilisation:
JTextArea textArea = new JTextArea();
DefaultContextMenu.addDefaultContextMenu(textArea);
Maintenant, le textArea
auront un menu contextuel quand il est clic droit sur.
Je vais corriger l'utilisation de cette méthode suggérée par @BullyWillPlaza.La raison est que lorsque j'essaie d'ajouter textArea à seulement contextMenu, il n'est pas visible, et si je l'ajoute à la fois à contextMenu et à certains panel, il deviendra: Association parent double différente si j'essaie de basculer vers l'éditeur de conception. Faites l'écoute de la souris comme ceci pour l'objet texte sur lequel vous devez avoir un popup. Qu'est-ce que cela va faire est quand vous faites un clic droit sur votre objet texte, il va ensuite ajouter cette fenêtre et l'afficher. De cette façon, vous ne rencontrez pas cette erreur. La solution que @BullyWillPlaza fait est très bonne, riche et rapide à implémenter dans votre programme, vous devriez donc l'essayer et voir comment vous l'aimez.
N'oubliez pas non plus que vous devez toujours importer ce contextMenu et créer une nouvelle instance. –
Après avoir utilisé le code ci-dessus, je reçois l'erreur en disant que « La méthode addMouseListener (MouseListener) dans le type figure est pas applicable pour les arguments (PopClickListener) » Cordialement, Vinay –
@ user1035905 Avez-vous assurez-vous que le ' PopClickListener' étend 'MouseAdapter'? – jjnguy
Comment l'obtenir avec la touche de menu contextuel du clavier? –