Java Swing'de nasıl sağ tıklama bağlam menüsü oluşturabilirim?


110

Şu anda JMenusağ tıklamada yeni bir örnek oluşturarak ve konumunu farenin konumuna ayarlayarak bir sağ tıklama bağlam menüsü oluşturuyorum ... Daha iyi bir yol var mı?

Yanıtlar:


141

Muhtemelen setVisible(true)menüden elle arıyorsunuz . Bu, menüde bazı kötü davranışlara neden olabilir.

show(Component, int x, int x)Yöntem kolları Eğer (Fareyle üzerine gelindiğinde şeyler vurgulama ve pop-up gerektiğinde kapatma) kullanarak, gerçekleşmesi gereken şeylerin hepsini setVisible(true)hemen herhangi bir ek davranışı eklemeden menüsünü gösterir.

Sağ tıklama açılır menüsü oluşturmak için basitçe bir JPopupMenu.

class PopUpDemo extends JPopupMenu {
    JMenuItem anItem;
    public PopUpDemo() {
        anItem = new JMenuItem("Click Me!");
        add(anItem);
    }
}

Ardından, yapmanız gereken tek şey, MouseListenermenünün açılmasını istediğiniz bileşenlere özel bir özellik eklemektir .

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());

Tabii ki, eğitimlerin biraz daha derinlemesine bir açıklaması var.

Not: Açılır menünün, kullanıcının tıkladığı yerden çok uzakta göründüğünü fark ederseniz , x ve y koordinatları için e.getXOnScreen()ve e.getYOnScreen()yöntemlerini kullanmayı deneyin .


Yukarıdaki kodu kullandıktan sonra, "Figure türündeki addMouseListener (MouseListener) yöntemi, argümanlar (PopClickListener) için geçerli değildir" şeklinde bir hata alıyorum. Saygılarımızla, Vinay

1
@ user1035905 emin olun mü PopClickListeneruzatır MouseAdapter?
jjnguy

Klavyedeki bağlam menüsü tuşuyla çalışmasını nasıl sağlıyorsunuz?
Christoffer Hammarström

Bu çözümün kleopatra'dan daha iyi olduğu tek durum, bazı özel mantığa ihtiyaç duyduğunuz zamandır (örneğin, farklı koşullar altında farklı açılır menüler); yine de, bağlam menüsü tuşuyla çalışmak için klavye dinleyicisi eklemelisiniz

2
ne anlama geliyor component?
Loint

117

Bu soru biraz eski - cevaplar gibi (ve öğretici de)

Swing'de bir popupMenu ayarlamak için mevcut api

myComponent.setComponentPopupMenu(myPopupMenu);

Bu şekilde, hem fare hem de klavye tetikleyicileri için otomatik olarak gösterilecektir (ikincisi LAF'a bağlıdır). Ayrıca, aynı açılır pencereyi bir kabın alt öğeleri arasında yeniden kullanmayı destekler. Bu özelliği etkinleştirmek için:

myChild.setInheritsPopupMenu(true);

2
@ user681159 hiçbirini bilmiyor - ve buna gerek yok, IMO, sadece api belgesini okuyun :-)
kleopatra

2
Bunu a ile nasıl kullanırsınız JTableki seçilen satırda veya sağ tıkladığınız satırda açılır? Veya bu senaryoda eski yöntem seçilecek olan mıdır?
Alex Burdusel

1
@Burfee, JTable'ı alt sınıflandırma yoluyla geliştirir veya geliştirir: getPopupLocation'ı (..) geçersiz kılın ve konumu daha sonra kullanmak için saklayın, tüm SwingX koleksiyon bileşenlerinde uygulanan yeni bir QA görün
kleopatra

18

Üzerinde olan bölümde bir Popup Menu Yetiştirmek içinde nasıl Kullanımına Menüleri maddesinde Java Tutorials nasıl kullanılacağı açıklanır JPopupMenusınıfı.

Öğreticideki örnek kod, MouseListenerbir açılır menü görüntülemesi gereken bileşenlere nasıl ekleneceğini gösterir ve buna göre menüyü görüntüler.

(Tanımladığınız yöntem, öğreticinin bir bileşendeki açılır menüyü gösterme yolunu sunma biçimine oldukça benzer.)


8

Aşağıdaki kod Windows, kopyala, kes, yapıştır, tümünü seç, geri al ve yinele işlevleriyle bilinen varsayılan bir bağlam menüsünü uygular . Ayrıca üzerinde çalışır Linuxve 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);
    }
}

Kullanımı:

JTextArea textArea = new JTextArea();
DefaultContextMenu.addDefaultContextMenu(textArea);

Şimdi textAreasağ tıklandığında bir içerik menüsü olacak.


Harika çözüm. Bir şey: tüm platformlarda düzgün çalışmak releasedEvent.isPopupTrigger()yerine kullanabilirsiniz / kullanmalısınız releasedEvent.getButton() == MouseEvent.BUTTON3.
Frederic Leitenberger

Anahtar dinleyicide bir hata daha: pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()bunların ikisi de olmalı Exveya olmamalıdır Ex. ExSürümü getMenuShortcutKeyMask()10+ java beri kullanılabilir.
Frederic Leitenberger

1

@BullyWillPlaza'nın önerdiği bu yöntemin kullanımını düzelteceğim. Nedeni şu ki, textArea'yı yalnızca contextMenu'ye eklemeye çalıştığımda görünmüyor ve bunu hem contextMenu'ye hem de bazı panele eklersem karşılıyor: Tasarım düzenleyicisine geçmeye çalışırsam farklı ebeveyn çift ilişkilendirmesi.

TexetObjcet.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (SwingUtilities.isRightMouseButton(e)){
                contextmenu.add(TexetObjcet);
                contextmenu.show(TexetObjcet, 0, 0);
            }
        }
    }); 

Popup açmanız gereken metin nesnesi için fare dinleyicisini bu şekilde yapın. Bunun yapacağı şey, metin nesnenize sağ tıkladığınızda o açılır pencereyi ekleyecek ve görüntüleyecektir. Bu şekilde bu hatayla karşılaşmazsınız. @BullyWillPlaza'nın ürettiği çözüm, programınızda uygulamak için çok iyi, zengin ve hızlıdır, bu yüzden onu nasıl sevdiğinizi görmek için denemelisiniz.


Ayrıca yine de bu contextMenu'yu içe aktarmanız ve yeni örnek oluşturmanız gerektiğini unutmayın.
Đumić Branislav
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.