Pop-up Menus

One of Swing's nifty components is JPopupMenu, a context menu that appears at the mouse location when you press the appropriate mouse button or keystroke. (On a two-button mouse, clicking the right mouse button invokes a pop-up menu. On a single-button Mac, you Command-click.) Which button you press depends on the platform you're using; fortunately, from the code's point of view you don't have to careSwing figures it out for you. The care and feeding of JPopupMenu is basically the same as any other menu. You use a different constructor (JPopupMenu( )) to create it, but otherwise, you build a menu and add elements to it the same way. The big difference is that you don't attach it to a JMenuBar. Instead, just pop up the menu whenever and wherever you need it. Prior to Java 5.0, this process is a little cumbersome; you have to register to receive the appropriate mouse events, check them to see if they are the pop-up trigger and then pop the menu manually. With Java 5.0, the process is simplified by having components manage their own pop-up menus. First, we'll show an example of explicit pop-up handling. The following example, PopupColorMenu, contains three buttons. You can use a JPopupMenu to set the color of each button or the background frame itself, depending on where you clickthe mouse.

 //file: PopUpColorMenu.java
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
 public class PopUpColorMenu implements ActionListener
 {
 Component selectedComponent;
 public PopUpColorMenu( ) {
 JFrame frame = new JFrame("PopUpColorMenu v1.0");
 final JPopupMenu colorMenu = new JPopupMenu("Color");
 colorMenu.add(makeMenuItem("Red"));
 colorMenu.add(makeMenuItem("Green"));
 colorMenu.add(makeMenuItem("Blue"));
 MouseListener mouseListener = new MouseAdapter( ) {
 public void mousePressed(MouseEvent e) { checkPopup(e); }
 public void mouseClicked(MouseEvent e) { checkPopup(e); }
 public void mouseReleased(MouseEvent e) { checkPopup(e); }
 private void checkPopup(MouseEvent e) {
 if (e.isPopupTrigger( )) {
 selectedComponent = e.getComponent( );
 colorMenu.show(e.getComponent( ), e.getX( ), e.getY( ));
 }
 }
 };
 Container content = frame.getContentPane( ); // unnecessary in 5.0+
 content.setLayout(new FlowLayout( ));
 JButton button = new JButton("Uno");
 button.addMouseListener(mouseListener);
 content.add(button);
 button = new JButton("Due");
 button.addMouseListener(mouseListener);
 content.add(button);
 button = new JButton("Tre");
 button.addMouseListener(mouseListener);
 content.add(button);
 frame.getContentPane( ).addMouseListener(mouseListener);
 frame.setSize(200,50);
 frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
 frame.setVisible(true);
 }
 public void actionPerformed(ActionEvent e) {
 String color = e.getActionCommand( );
 if (color.equals("Red"))
 selectedComponent.setBackground(Color.red);
 else if (color.equals("Green"))
 selectedComponent.setBackground(Color.green);
 else if (color.equals("Blue"))
 selectedComponent.setBackground(Color.blue);
 }
 private JMenuItem makeMenuItem(String label) {
 JMenuItem item = new JMenuItem(label);
 item.addActionListener( this );
 return item;
 }
 public static void main(String[] args) {
 new PopUpColorMenu( );
 }
 }


Screenshot-8 shows the example in action; the user is preparing to change the color of the bottom button.

Screenshot-8. The PopupColorMenu app
Java ScreenShot

Because the pop-up menu is triggered by mouse events (in this example), we need to register a MouseListener for any of the components to which it applies. In this example, all three buttons and the content pane of the frame are eligible for the color pop-up menu. Therefore, we add a mouse-event listener for all these components explicitly. The same instance of an anonymous inner MouseAdapter subclass is used in each case. In this class, we override the mousePressed( ), mouseReleased( ), and mouseClicked( ) methods to display the pop-up menu when we get an appropriate event. How do we know what an "appropriate event" is? Fortunately, we don't need to worry about the specifics of our user's platform; we just need to call the event's isPopupTrigger( ) method. If this method returns true, we know the user has done whatever normally displays a pop-up menu on his system. Once we know that the user wants to raise a pop-up menu, we display it by calling its show( ) method with the mouse event coordinates as arguments. If we want to provide different menus for different types of components or the background, we create different mouse listeners for each different kind of component. The mouse listeners invoke different kinds of pop-up menus as appropriate. The only thing left is to handle the action events from the pop-up menu items. We use a helper method called makeMenuItem( ) to register the PopUpColorMenu window as an action listener for every item we add. The example implements ActionListener and has the required actionPerformed( ) method. This method reads the action command from the event, which is equal to the selected menu item's label by default. It then sets the background color of the selected component appropriately.

Java ScreenShot
Comments