Attualmente sto creando un menu di scelta rapida facendo clic con il pulsante destro del mouse e istanziando un nuovo JMenu
con il tasto destro del mouse e impostando la sua posizione su quella della posizione del mouse ... Esiste un modo migliore?Come creare un menu di scelta rapida con clic destro in Java Swing?
risposta
Probabilmente si sta chiamando manualmente setVisible(true)
sul menu. Ciò può causare un comportamento scorretto nei buggy nel menu.
Il metodo show(Component, int x, int x)
gestisce tutte le cose che devono accadere, (Evidenziando le cose al passaggio del mouse e chiudere il pop-up quando necessario) in cui l'utilizzo setVisible(true)
solo mostra il menu senza l'aggiunta di alcun comportamento aggiuntivo.
Per creare un menu popup con il tasto destro, creare semplicemente un JPopupMenu
.
class PopUpDemo extends JPopupMenu {
JMenuItem anItem;
public PopUpDemo(){
anItem = new JMenuItem("Click Me!");
add(anItem);
}
}
Poi, tutto quello che dovete fare è aggiungere una consuetudine MouseListener
per i componenti che si desidera che il menu a comparsa per.
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());
Naturalmente, le esercitazioni hanno una spiegazione slightly more in-depth.
Nota: Se si nota che il menu a comparsa vengono visualizzati lontano dal punto in cui l'utente fa clic, provare a utilizzare i e.getXOnScreen()
e e.getYOnScreen()
metodi di coordinate xe y.
C'è una sezione su Bringing Up a Popup Menu nell'articolo How to Use Menus di The Java Tutorials che spiega come utilizzare la classe JPopupMenu
.
Il codice di esempio nel tutorial mostra come aggiungere MouseListener
s ai componenti che dovrebbero visualizzare un menu a comparsa e visualizzare il menu di conseguenza.
(Il metodo che si descrive è abbastanza simile al modo in cui il tutorial presenta il modo per mostrare un menu pop-up su un componente.)
Questa domanda è un po 'vecchio - come lo sono le risposte (e il tutorial così)
l'API di corrente per l'impostazione di un popupMenu in Swing è
myComponent.setComponentPopupMenu(myPopupMenu);
In questo modo sarà mostrato automagically , sia per i trigger di mouse e tastiera (quest'ultimo dipende da LAF). Inoltre, supporta il riutilizzo dello stesso popup sui figli di un contenitore. Per abilitare questa caratteristica:
myChild.setInheritsPopupMenu(true);
Il codice seguente implementa un menu di scelta rapida di default conosciuta da Windows
con copia, taglia, incolla, seleziona tutto, annullare e ripetere le funzioni. Funziona anche su Linux
e 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);
Ora il textArea
avranno un menu contestuale quando si fa click destro su.
Correggerò l'utilizzo per il metodo suggerito da @BullyWillPlaza.Il motivo è che quando provo ad aggiungere aggiungi textArea solo a contextMenu non è visibile, e se lo aggiungo a contextMenu e ad alcuni panel ecounters: Genera doppia associazione diversa se provo a passare all'editor di progettazione.
TexetObjcet.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)){
contextmenu.add(TexetObjcet);
contextmenu.show(TexetObjcet, 0, 0);
}
}
});
Crea un listener del mouse come questo per l'oggetto testo su cui è necessario avere un popup. Ciò che questo farà sarà quando clicchi con il tasto destro sul tuo oggetto di testo per aggiungere quel popup e visualizzarlo. In questo modo non si verifica quell'errore. La soluzione che @BullyWillPlaza ha creato è molto buona, ricca e veloce da implementare nel tuo programma, quindi dovresti provare a vedere come ti piace.
Inoltre, non dimenticare che devi ancora importare quel menu contestuale e creare una nuova istanza. –
Dopo aver utilizzato il codice di cui sopra, ottengo l'errore dicendo che "Il metodo addMouseListener (MouseListener) nel tipo figura non è applicabile per gli argomenti (PopClickListener)" Saluti, Vinay –
@ user1035905 Hai assicurarsi che il ' PopClickListener' estende 'MouseAdapter'? – jjnguy
Come si fa a farlo funzionare con il tasto del menu di scelta rapida sulla tastiera? –