6.1.4 jmenuitem class
The jmenuitem component is a predefined component that you can select on the menu bar. As a subclass of abstractbutton, jmenuitem is a special button component and its behavior is similar to jbutton. In addition to being a subclass of abstractbutton, The jmenuitem class shares the data model of jbutton (implemented by the buttonmodel interface and defaultbuttonmodel ).
Create a jmenuitem component
Jmenuitem has six constructors. These constructors enable us to initialize the string or icon of the menu item and the hotkey of the menu item. There is no explicit constructor that allows us to set all three options during creation, unless we use them as part of the action.
public JMenuItem()JMenuItem jMenuItem = new JMenuItem(); public JMenuItem(Icon icon)Icon atIcon = new ImageIcon("at.gif");JMenuItem jMenuItem = new JMenuItem(atIcon); public JMenuItem(String text)JMenuItem jMenuItem = new JMenuItem("Cut"); public JMenuItem(String text, Icon icon)Icon atIcon = new ImageIcon("at.gif");JMenuItem jMenuItem = new JMenuItem("Options", atIcon); public JMenuItem(String text, int mnemonic)JMenuItem jMenuItem = new JMenuItem("Cut", KeyEvent.VK_T); public JMenuItem(Action action)Action action = ...;JMenuItem jMenuItem = new JMenuItem(action);
The hot key allows us to browse and select the menu through the keyboard. For example, if the menu item appears in the open edit menu on Windows, you can simply press Alt-t to select the cut menu. The shortcut key of a menu item usually appears as an underline in the menu text label. However, if the character does not appear in the text tag, or there is no text tag, the user will not receive any obvious prompt. Characters are identified by different constants in the Java. AWT. event. keyevent class.
Other platforms may provide other selected hotkeys. Generally, the Alt key is used on UNIX platforms, while the command key is used on Macintosh platforms.
Jmenuitem attributes
Jmenuitem has multiple attributes. About 100 attributes are inherited by various superclasses. Table 6-3 shows the specific 10 attributes of jmenuitem.
Jmenuitem attributes
Attribute name
Data Type
Accessibility
Accelerator
Keystroke
Read/write binding
Accessiblecontext
Accessiblecontext
Read-Only
Armed
Boolean
Read/write
Component
Component
Read-Only
Enabled
Boolean
Write-only binding
Menudragmouselisteners
Menudragmouselistener []
Read-Only
Menukeylisteners
Menukeylistener []
Read-Only
Subelements
Menuelement []
Read-Only
UI
Menuelementui
Write-only binding
Uiclassid
String
Read-Only
An interesting property is accelerator. As explained in chapter 2nd, keystroke is a factory class that allows us to create instances based on combinations of buttons and identifiers. For example, the following code statement is from the example in list 6-1 in this chapter. use ctrl-X as the shortcut key to associate it with a specific menu item:
KeyStroke ctrlXKeyStroke = KeyStroke.getKeyStroke("control X");cutMenuItem.setAccelerator(ctrlXKeyStroke);
The read-only component and subelement attributes are part of the menuelement interface implemented by jmenuitem. The Component Attribute is the Renderer of the menu item (jmenuitem itself ). The subelement attribute is empty (that is, an empty array, rather than null), because jmenuitem does not have a subclass.
Process jmenuitem events
We can use at least five different methods within jmenuitem to process events. The component inherits the capabilities that allow us to trigger changeevent and actionevent through the methods registered by mongoactbutton's changelistener and actionlistener. The jmenuitem component supports registering the menukeylistener and menudragmouselistener objects when the menukeyevent and menudragmouseevent events occur. These technologies will be discussed in later chapters. The fifth method is to pass the action to the jmenuitem constructor, which is similar to a special method for listening with actionlistener. For more information about using action, see the discussion about using action objects in the menu in the "jmenu class" section later in this chapter.
Use changelistener to listen to jmenuitem events
Generally, we do not register changelistener with jmenuitem. However, presenting an ideal example helps to explain more clearly the changes of jmenuitem's buttonmodel data model. The event changes are the same arm, press, and select as jbutton. However, their names are somewhat confusing because the selected model attributes are not set.
When you move the cursor over the menu option and the menu becomes selected, jmenuitem is armed. When the user releases the mouse button, jmenuitem is pressed. After pressing, the menu item changes to unpressed and unarmed. When the menu item changes to "pressed" or "not pressed", abstractbutton will be notified of model changes, so that the actionlistener object registered in the menu item will be notified. The button model of a common jmenuitem is not reported to be selected. If we move the mouse over another menu item without selection, the first menu item will automatically change unarmed. To help us better understand different changes, figure 6-5 shows a sequence diagram.
Use actionlistener to listen to jmenuitem events
The better listener associated with jmenuitem is actionlistener, or an action is passed to the constructor. This allows us to determine which menu item is selected. When you release the mouse button on the jmenuitem that is part of the Open menu, the registered actionlistener object will be notified. If you select a menu by pressing the keyboard (arrow key or hot key) or by pressing the shortcut key, the registered listener will also be notified.
An action occurs when you want the menu to be selected. You must add an actionlistener for each jmenuitem. There is no automatic method so that we can register an actionlistener for jmenu or jmenubar so that the jmenuitem object contained in it can notify an actionlistener.
The example program in list 6-1 associates an identical actionlistener for each jmenuitem:
class MenuActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Selected: " + e.getActionCommand()); }}
More often, however, we associate a different action for each menu item so that each menu item can respond differently.
Tip: we do not need to create a custom actionlistener for the component and register it. We can create a custom action and call the setaction () method on the component.
Use menukeylistener to listen to jmenuitem events
Menukeyevent is a special keyevent used by jmenu and jmenuitem in the user interface class, so that the component can monitor when its keyboard Hot Key is pressed. To listen to such keyboard input, each menu component registers a menukeylistener to listen for the corresponding input. If the keyboard Hot Key is pressed, the event will be processed and will not be sent to the registered listener. If the keyboard hot key is not pressed, the registered keyboard listener (instead of the menu key listener) will be notified.
The menukeylistener interface is defined as follows:
public interface MenuKeyListener extends EventListener { public void menuKeyPressed(MenuKeyEvent e); public void menuKeyReleased(MenuKeyEvent e); public void menuKeyTyped(MenuKeyEvent e);}
Generally, we do not need to register the listener object of this type, even if we want. If we are sure to do this, and if menukeyevent occurs (that is, a key is pressed/released), every jmenu in jmenubar will be notified, just like opening every jmenuitem (or subclass) in the menu) all have a registered menukeylistener. This includes prohibited menu items so that they can process the hot keys pressed. The menukeyevent class is defined as follows:
public class MenuKeyEvent extends KeyEvent { public MenuKeyEvent(Component source, int id, long when, int modifiers, int keyCode, char keyChar, MenuElement path[], MenuSelectionManager mgr); public MenuSelectionManager getMenuSelectionManager(); public MenuElement[] getPath();}
Determine that the selected path is the work of menuselectionmanager. The selection path is a set of menu elements from the jmenu on the top-level jmenubar to the selected component. In most cases, the manager works behind the scenes without worrying about it.
Use menudragmouselistener to listen to jmenuitem events
Similar to menukeyevent, menudragmouseevent is a special event type used internally by the jmenu and jmenubar user interfaces. As shown in its name, menudragmouseevent is a special type of mouseevent. The user interface class uses the listener to maintain the selection path, so as to determine the selected menu items. It is defined as follows:
public interface MenuDragMouseListener extends EventListener { public void menuDragMouseDragged(MenuDragMouseEvent e); public void menuDragMouseEntered(MenuDragMouseEvent e); public void menuDragMouseExited(MenuDragMouseEvent e); public void menuDragMouseReleased(MenuDragMouseEvent e);}
Similar to menukeylistener, we usually do not need to monitor this event in person. If we are more interested in when a menu or sub-menu is displayed, the better listener to be registered is menulistener. This listener can be registered to jmenu, but cannot be registered to a single jmenuitem. We will understand this in the next section describing jmenu.
Menudragmouseevent class definition. The parameters of the menudragmouselistener method are as follows:
public class MenuDragMouseEvent extends MouseEvent { public MenuDragMouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger, MenuElement path[], MenuSelectionManager mgr); public MenuSelectionManager getMenuSelectionManager(); public MenuElement[] getPath();}
Custom jmenuitem View
Similar to jmenubar, the predefined perception type provides different jmenuitem appearances and default set of uiresource values. Figure 6-3 shows the jmenuitem appearance of the pre-installed set: motif, windows, and ocean.
Table 6-4 shows the set of uiresource attributes of jmenuitem. The jmenuitem component provides 20 different attributes.
Jmenuitem uiresource Element
Attribute string
Object Type
Menuitem. acceleratordelimiter
String
Menuitem. acceleratorfont
Font
Menuitem. acceleratorforeground
Color
Menuitem. acceleratorselectionforeground
Color
Menuitem. actionmap
Actionmap
Menuitem. arrowicon
Icon
Menuitem. Background
Color
Menuitem. Border
Border
Menuitem. borderpainted
Boolean
Menuitem. checkicon
Icon
Menuitem. commandsound
String
Menuitem. disabledforeground
Color
Menuitem. Font
Font
Menuitem. Foreground
Color
Menuitem. Margin
Insets
Menuitem. opaque
Boolean
Menuitem. selectionbackground
Color
Menuitem. selectionforeground
Color
Menuitem. texticongap
Integer
Menuitemui
String
6.1.5 jmenu class
The jmenu component is a basic menu item placed on jmenubar. When a jmenu is selected, the menu items are displayed in jpopupmenu. For jmenuitem, the data model of jmenu is implemented by a buttonmodel, or, more specifically, defaultbutonmodel.
Create a jmenu component
Jmenu has four constructors that allow us to initialize the string tag of the menu:
public JMenu()JMenu jMenu = new JMenu();public JMenu(String label)JMenu jMenu = new JMenu("File");public JMenu(String label, boolean useTearOffs)public JMenu(Action action)Action action = ...;JMenu jMenu = new JMenu(action);
One constructor is used for the tear-off menu. However, the tear-off menu is not currently supported, so its parameters are ignored. The fourth constructor uses the properties in action to fill the menu.
Note: The tear-off menu is displayed in a window and remains open after selection, rather than automatically closed.
Add menu items to jmenu
Once we have jmenu, we need to add the jmenuitem object to it; otherwise, the menu will not display any selection. There are five ways to add a defined menu item to jmenu, one for adding a separator:
public JMenuItem add(JMenuItem menuItem);public JMenuItem add(String label);public Component add(Component component);public Component add(Component component, int index);public JMenuItem add(Action action);public void addSeparator();
In list 6-1 above this chapter, all jmenuitem components are added to the jmenu component through the first add () method. For convenience, we can pass the text label of jmenuitem to the add () method of jmenu. This method creates a menu item, sets its label, and returns the single component of the new dish. Then we can bind the menu item event processor to this new menu item. The third add () method indicates that we can place any component on jmenu, not just jmenuitem. The fourth add () method allows us to place components by position. The last add () method variation with an action parameter will be discussed in the next section.
We can use addseparator () method of jmenu to add a separator bar. For example, in list 6-1, the File menu is created using code similar to the following:
JMenu fileMenu = new JMenu("File");JMenuItem newMenuItem = new JMenuItem("New");fileMenu.add(newMenuItem);JMenuItem openMenuItem = new JMenuItem("Open");fileMenu.add(openMenuItem);JMenuItem closeMenuItem = new JMenuItem("Close");fileMenu.add(closeMenuItem);fileMenu.addSeparator();JMenuItem saveMenuItem = new JMenuItem("Save");fileMenu.add(saveMenuItem);fileMenu.addSeparator();JMenuItem exitMenuItem = new JMenuItem("Exit");fileMenu.add(exitMenuItem);
Note that addspeparator () calls enclose the call for adding the Save menu item.
In addition to adding menu items at the end of the menu, you can insert menu items at the specified position or the delimiter at the specified position, as shown below:
public JMenuItem insert(JMenuItem menuItem, int pos);public JMenuItem insert(Action a, int pos);public void insertSeparator(int pos);
After a menu is added to jmenu, it is added to the internal jpopupmenu.
Use action object in the menu
The aciton interface and its associated classes are described in Chapter 2nd. Action is an extension of the actionlistener interface and contains some special attributes used to customize Components associated with its implementation.
With abstractaction, we can easily define text labels, icons, hotkeys, tooltip text, allowable states, and an actionlistener separated from components. Then we can use the associated action to create a component, without having to specify text labels, icons, hotkeys, tooltip text, allowable status, or actionlistener for the component, because these attributes come from action. For more information, see Chapter 2nd.
For demonstration purposes, a specific implementation of abstractaction is created in list 6-2 and added to jmenu multiple times. Once the action is added to jmenu, selecting jmenuitem will display a pop-up dialog box using the joptionpane class, which will be discussed in chapter 9th.
import java.awt.*;import java.awt.event.*;import javax.swing.*;public class ShowAction extends AbstractAction { Component parentComponent; public ShowAction(Component parentComponent) { super("About"); putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_A)); this.parentComponent = parentComponent; } public void actionPerformed(ActionEvent actionEvent) { Runnable runnable = new Runnable() { public void run() { JOptionPane.showMessageDialog( parentComponent, "About Swing", "About Box V2.0", JOptionPane.INFORMATION_MESSAGE); } }; EventQueue.invokeLater(runnable); }}
The following code creates a showaction and a jmenuitem for the file and edit menus in the example program 6-1 in the list. You do not need to display the set menu item attribute. It will have an about text label and a hot key, and will execute the defined actionreceivmed () method as its actionlistener. In fact, we can create an action once and associate it to multiple places (or other components that support adding action objects ).
Action showAction = new ShowAction(aComponent);JMenuItem fileAbout = new JMenuItem(showAction);fileMenu.add(fileAbout);JMenuItem editAbout = new JMenuItem(showAction);editMenu.add(editAbout);
The side effect of using abstractaction is that when the setenabled (false) method is used to disable action, all components created by the setenabled (false) method are disabled.
Jmenu attributes
In addition to the 100 attributes inherited by jmenu, Table 6-5 displays 16 jmenu-specific attributes. Some of these attributes overwrite the behavior of the inherited attributes. For example, the setting method of the accelerator attribute will throw an error when we try to assign a value to this attribute. In other words, shortcuts are not supported by jmenu objects. Other attributes describe the current status of the jmenu object and its menu components.
Jmenu attributes
Attribute name
Data Type
Accessibility
Accelerator
Keystroke
Write only
Accessiblecontext
Accessiblecontext
Read-Only
Component
Component
Read-Only
Delay
Int
Read/write
Itemcount
Int
Read-Only
Menucomponentcount
Int
Read-Only
Menucomponents
Component []
Read-Only
Menulisteners
Menulistener []
Read-Only
Model
Buttonmodel
Write-only binding
Popupmenu
Jpopupmenu
Read-Only
Popupmenuvisible
Boolean
Read/write
Selected
Boolean
Read/write
Subelements
Menuelement []
Read-Only
Tearoff
Boolean
Read-Only
Toplevelmenu
Boolean
Read-Only
Uiclassid
String
Read-Only
The delay attribute indicates the time elapsed between jmenu and jpopupmenu. The default value is 0, indicating that the sub-menu is displayed immediately. An attempt to set this value to a negative value will throw illegalargumentexception.
Select menu Components
Generally, we do not need to listen to the jmenu component selection. We only need to listen to the selection of a single jmenuitem component. However, compared with jmenuitem, we are interested in the different changeevent methods used by jmenu. In addition, when a menu is popped up or closed, menuevent will notify us.
Use changelistener to listen to jmenu events
Similar to jmenuitem, if we are interested in modifying the underlying buttonmodel, we can register changelistener with jmenu. The strange thing is that the only change in the status of the jmenu buttonmodel is the selected attribute. When selected, jmenu displays its menu items. When not selected, the pop-up menu disappears.
Use menulistener to listen to jmenu events
A better way to monitor when a pop-up menu is displayed or hidden is to register a menulistener object with the jmenu object. It is defined as follows:
Public interface menulistener extends eventlistener {
Public void menucanceled (menuevent E );
Public void menudeselected (menuevent E );
Public void menuselected (menuevent E );
}
By registering menulistener, we will be notified when jmenu is selected before the pop-up menu is opened. This allows us to customize its menu options. In addition to notifications about when the associated pop-up menu is popped up, we will also be notified when the menu is deselected and disabled. As shown in the following menuevent class definition, the only information provided by an event is the source (menu ):
public class MenuEvent extends EventObject { public MenuEvent(Object source);}
Tip: if we choose to dynamically customize items on the jmenu, make sure to call revalidate () because the component will wait until we update the display.
Custom jmenu View
Similar to jmenubar and jmenuitem, the predefined view provides different jmenu appearances and default set of uiresource values. Figure 6-3 shows the jmenu Object Appearance of the pre-installed visual type set.