17.9. Component-Managed Pop-upsThings get a bit easier in Java 5.0, using the new pop-up menu API for components. In Java 5.0, any JComponent can manage a JPopupMenu directly with the setComponentPopupMenu( ) method. JComponents can also be told to simply inherit their parent container's pop-up menu via the setInheritsPopupMenu( ) method. This combination makes it very simple to implement a context menu that should appear in many components within a container. Unfortunately, this doesn't lend itself well to our previous example (PopupColorMenu) for two reasons. First, we need to know which component the mouse was in when the pop-up was triggered and we don't get that information using this API. The pop-up handling is actually delegated to the container, not inherited. Second, not all types of components are registered to receive mouse events by default.[*] As a result, we'll create a new example that is more appropriate for a "one context menu to rule them all" application. The following example, ContextMenu, shows a TextArea and TextField that both inherit the same JPopupMenu from their JPanel container. When you select a menu item, the action is displayed in the text area.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ContextMenu implements ActionListener { JTextArea textArea = new JTextArea( ); public ContextMenu( ) { final JPopupMenu contextMenu = new JPopupMenu("Edit"); contextMenu.add(makeMenuItem("Save")); contextMenu.add(makeMenuItem("Save As")); contextMenu.add(makeMenuItem("Close")); JFrame frame = new JFrame("ContextMenu v1.0"); JPanel panel = new JPanel( ); panel.setLayout( new BorderLayout( ) ); frame.add( panel ); panel.setComponentPopupMenu( contextMenu ); textArea.setInheritsPopupMenu( true ); panel.add( BorderLayout.CENTER, textArea ); JTextField textField = new JTextField( ); textField.setInheritsPopupMenu( true ); panel.add( BorderLayout.SOUTH, textField ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setSize(400,200); frame.setVisible(true); } public void actionPerformed( ActionEvent e ) { textArea.append( e.getActionCommand( ) +"\n" ); } private JMenuItem makeMenuItem(String label) { JMenuItem item = new JMenuItem(label); item.addActionListener( this ); return item; } public static void main(String[] args) { new ContextMenu( ); } } We've constructed our JPopupMenu as before, but this time we are not responsible for listening for mouse clicks or triggering the pop-up explicitly. Instead we use the setComponentPopupMenu( ) method to ask the JPanel to handle it for us. We use setInheritsPopupMenu( ) on both the JTextArea and JTextField so that they will both delegate pop-up trigger mouse clicks to the JPanel automatically. |