簡體   English   中英

如何在Java Swing中創建右鍵單擊上下文菜單?

[英]How do I create a right click context menu in Java Swing?

我正在創建一個右鍵單擊上下文菜單,通過右鍵單擊實例化一個新的JMenu並將其位置設置為鼠標的位置......有更好的方法嗎?

您可能在菜單上手動調用setVisible(true) 這可能會導致菜單中出現一些討厭的錯誤行為。

show(Component, int x, int x)方法處理您需要發生的所有事情(在鼠標懸停時突出顯示內容並在必要時關閉彈出窗口),其中使用setVisible(true)只顯示菜單而不添加任何其他行為。

要創建一個右鍵單擊彈出菜單,只需創建一個JPopupMenu

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坐標。

這個問題有點陳舊 - 答案也是如此(以及教程)

用於在Swing中設置popupMenu的當前api是

myComponent.setComponentPopupMenu(myPopupMenu);

這種方式將自動顯示鼠標和鍵盤觸發器(后者取決於LAF)。 此外,它支持在容器的子項中重復使用相同的彈出窗口。 要啟用該功能:

myChild.setInheritsPopupMenu(true);

有一個部分造就了彈出菜單如何使用菜單的文章Java教程這也解釋了如何使用JPopupMenu類。

本教程中的示例代碼顯示了如何將MouseListener添加到應顯示彈出菜單的組件,並相應地顯示菜單。

(您描述的方法與教程提供在組件上顯示彈出菜單的方式非常相似。)

以下代碼實現了Windows已知的默認上下文菜單,包括復制,剪切,粘貼,全選,撤消和重做功能。 它也適用於LinuxMac 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在右鍵單擊時將具有上下文菜單。

我將更正@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所做的解決方案非常好,在您的程序中實現豐富和快速,因此您應該嘗試它,我們看看您喜歡它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM