2009-04-20 65 views

Trả lời

127

Bạn có lẽ bằng tay gọi setVisible(true) trên menu. Điều đó có thể gây ra một số hành vi buggy khó chịu trong menu.

Phương pháp show(Component, int x, int x) xử lý mọi thứ bạn cần xảy ra, (Làm nổi bật mọi thứ khi di chuột qua và đóng cửa sổ bật lên khi cần) khi sử dụng setVisible(true) chỉ hiển thị menu mà không thêm bất kỳ hành vi bổ sung nào.

Để tạo menu bật lên nhấp chuột phải, chỉ cần tạo JPopupMenu.

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

Sau đó, tất cả những gì bạn cần làm là thêm tùy chỉnh MouseListener vào các thành phần bạn muốn trình đơn bật lên.

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

Tất nhiên, hướng dẫn có giải thích slightly more in-depth.

Lưu ý: Nếu bạn nhận thấy rằng các menu popup xuất hiện cách khỏi nơi người dùng nhấn vào, hãy thử sử dụng e.getXOnScreen()e.getYOnScreen() phương pháp để tọa độ x và y.

+0

Sau khi sử dụng mã trên, tôi nhận được lỗi nói rằng "Phương thức addMouseListener (MouseListener) trong loại Hình không áp dụng cho các đối số (PopClickListener)" Trân trọng, Vinay –

+1

@ user1035905 Bạn có chắc chắn rằng ' PopClickListener' mở rộng 'MouseAdapter'? – jjnguy

+0

Làm cách nào để bạn làm việc với phím menu ngữ cảnh trên bàn phím? –

18

Có một phần trên Bringing Up a Popup Menu trong bài viết How to Use Menus của The Java Tutorials giải thích cách sử dụng lớp JPopupMenu.

Mã ví dụ trong hướng dẫn cho biết cách thêm MouseListener giây vào các thành phần sẽ hiển thị menu bật lên và hiển thị menu tương ứng.

(Phương pháp bạn mô tả là khá tương tự như cách hướng dẫn trình bày các cách để hiển thị một menu pop-up trên một thành phần.)

105

Câu hỏi này là một chút cũ - như là những câu trả lời (và hướng dẫn cũng)

Các api hiện để thiết lập một popupMenu trong Swing là

myComponent.setComponentPopupMenu(myPopupMenu); 

Bằng cách này nó sẽ được hiển thị Automagically , cho cả kích hoạt chuột và bàn phím (sau này phụ thuộc vào LAF). Ngoài ra, nó hỗ trợ tái sử dụng cùng một cửa sổ bật lên trên con của vùng chứa. Để bật tính năng đó:

myChild.setInheritsPopupMenu(true); 
+0

bạn có thể vui lòng cung cấp hướng dẫn với api đã cập nhật không? –

+2

@ user681159 không biết bất kỳ điều gì - và không cần thiết, IMO, chỉ cần đọc tài liệu api :-) – kleopatra

+0

@downvoter - cẩn thận để giải thích? – kleopatra

5

Các mã sau đây thực hiện một menu ngữ cảnh mặc định được biết đến từ Windows với sao chép, cắt, dán, chọn tất cả, undo và redo chức năng. Nó cũng hoạt động trên 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); 
    } 
} 

Cách sử dụng:

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

Bây giờ textArea sẽ có một menu ngữ cảnh khi nó là phải nhấp vào.

0

Tôi sẽ sửa cách sử dụng cho phương thức mà @BullyWillPlaza đề xuất.Lý do là khi tôi cố gắng thêm textArea vào chỉ contextMenu nó không hiển thị, và nếu tôi thêm nó vào cả hai contextMenu và một số bảng nó ecounters: cha mẹ khác nhau đôi hiệp hội nếu tôi cố gắng để chuyển sang thiết kế trình soạn thảo.

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

Làm cho người nghe chuột như thế này cho đối tượng văn bản bạn cần bật lên bật lên. Điều này sẽ làm là khi bạn nhấp chuột phải vào đối tượng văn bản của bạn sau đó nó sẽ thêm popup và hiển thị nó. Bằng cách này bạn không gặp phải lỗi đó. Giải pháp mà @BullyWillPlaza thực hiện rất tốt, phong phú và nhanh chóng để triển khai trong chương trình của bạn, do đó bạn nên thử cách chúng tôi thấy bạn thích nó như thế nào.

+0

Cũng đừng quên bạn vẫn cần phải nhập ngữ cảnh đóMenu và tạo cá thể mới. –

Các vấn đề liên quan