В настоящее время я создаю контекстное меню, вызываемое щелчком правой кнопкой мыши, создавая экземпляр нового JMenu
при щелчке правой кнопкой мыши и устанавливая его местоположение в соответствии с положением мыши ... Есть ли лучший способ?
Как создать контекстное меню правой кнопки мыши в Java Swing?
Ответы (5)
Вероятно, вы вручную вызываете setVisible(true)
в меню. Это может вызвать неприятные ошибки в меню.
Метод show(Component, int x, int x)
обрабатывает все, что вам нужно, (выделение элементов при наведении курсора и закрытие всплывающего окна при необходимости), где использование setVisible(true)
просто показывает меню без добавления какого-либо дополнительного поведения.
Чтобы создать всплывающее меню при щелчке правой кнопкой мыши, просто создайте _4 _ а>.
class PopUpDemo extends JPopupMenu {
JMenuItem anItem;
public PopUpDemo() {
anItem = new JMenuItem("Click Me!");
add(anItem);
}
}
Затем все, что вам нужно сделать, это добавить пользовательский MouseListener
к компонентам, для которых должно отображаться всплывающее меню.
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());
Конечно, в руководствах есть немного более подробное описание объяснение.
Примечание. Если вы заметили, что всплывающее меню появляется далеко от того места, где щелкнул пользователь, попробуйте использовать методы e.getXOnScreen()
и e.getYOnScreen()
для координат x и y.
PopClickListener
расширяет MouseAdapter
?
- person jjnguy; 08.11.2011
component
?
- person Loint; 30.05.2016
Этот вопрос немного устарел - как и ответы (и само руководство)
Текущий api для настройки popupMenu в Swing:
myComponent.setComponentPopupMenu(myPopupMenu);
Таким образом, это будет отображаться автоматически, как для триггеров мыши, так и для клавиатуры (последнее зависит от LAF). Кроме того, он поддерживает повторное использование одного и того же всплывающего окна для дочерних элементов контейнера. Чтобы включить эту функцию:
myChild.setInheritsPopupMenu(true);
JTable
, чтобы он появлялся в выбранной строке или в строке, где вы щелкаете правой кнопкой мыши? Или в этом случае следует выбрать старый метод?
- person Alex Burdusel; 29.12.2013
Есть раздел Открытие всплывающего меню в статье Как использовать меню в Учебники по Java, в которых объясняется, как использовать _ 1_ класс.
В примере кода в руководстве показано, как добавить MouseListener
s к компонентам, которые должны отображать всплывающее меню и соответственно отображать меню.
(Метод, который вы описываете, довольно похож на способ, которым в учебнике представлен способ отображения всплывающего меню на компоненте.)
Следующий код реализует контекстное меню по умолчанию, известное из Windows
, с функциями копирования, вырезания, вставки, выбора всего, отмены и повтора. Он также работает с Linux
и 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);
}
}
Использование:
JTextArea textArea = new JTextArea();
DefaultContextMenu.addDefaultContextMenu(textArea);
Теперь textArea
будет иметь контекстное меню при щелчке правой кнопкой мыши.
releasedEvent.isPopupTrigger()
вместо releasedEvent.getButton() == MouseEvent.BUTTON3
для правильной работы на всех платформах.
- person Frederic Leitenberger; 22.07.2020
pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
они должны быть либо Ex
, либо не Ex
. Ex
версия getMenuShortcutKeyMask()
доступна только с версии java 10+.
- person Frederic Leitenberger; 22.07.2020
Я исправлю использование этого метода, предложенного @BullyWillPlaza. Причина в том, что когда я пытаюсь добавить textArea только в contextMenu, оно не отображается, и если я добавляю его как в contextMenu, так и в какую-то панель, он обнаруживает: Другая родительская двойная ассоциация, если я пытаюсь переключиться в редактор дизайна.
TexetObjcet.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)){
contextmenu.add(TexetObjcet);
contextmenu.show(TexetObjcet, 0, 0);
}
}
});
Сделайте такой слушатель мыши для текстового объекта, на котором вам нужно всплывающее окно. Что это будет делать, так это когда вы щелкнете правой кнопкой мыши по текстовому объекту, он добавит это всплывающее окно и отобразит его. Таким образом, вы не столкнетесь с этой ошибкой. Решение, созданное @BullyWillPlaza, очень хорошее, богатое и быстрое для реализации в вашей программе, поэтому вы должны попробовать его, чтобы увидеть, как оно вам нравится.