2009-04-20 8 views

Répondre

127

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.

+0

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 –

+1

@ user1035905 Avez-vous assurez-vous que le ' PopClickListener' étend 'MouseAdapter'? – jjnguy

+0

Comment l'obtenir avec la touche de menu contextuel du clavier? –

18

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.)

105

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); 
+0

pouvez-vous s'il vous plaît fournir un tutoriel avec l'API mis à jour? –

+2

@ user681159 ne sais pas tout - et ce n'est pas nécessaire, OMI, il suffit de lire le doc api :-) – kleopatra

+0

@downvoter - soin d'expliquer? – kleopatra

5

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.

0

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.

+0

N'oubliez pas non plus que vous devez toujours importer ce contextMenu et créer une nouvelle instance. –

Questions connexes