The first two chapters of this book describe some low-level swing components. This chapter will go deep into swing menu-oriented components. Menus and toolbar make our programs more friendly by providing visual Command Options. Although the swing component can support command sequences with multiple buttons, menus are designed to provide graphical selection with the mouse instead of using the keyboard.
The use of menu components to be discussed in this chapter is as follows:
- For cascading menus, we can create a jmenu component and add it to jmenubar.
- For the optional menu in jmenu, we can create a jmenuitem component and add it to jmenu.
- To create a sub-menu, we can add a new jmenu to the jmenu and add the jmenuitem option to the new menu.
- Then, when a jmenu is selected, the system displays its current component set in jpopupmenu.
In addition to the basic jmenuitem elements, this chapter will discuss other menu items, such as jcheckboxmenuitem and jradiobuttonmenuitem. We can place these two menu items in jmenu. We will also discuss the jseparator class, which can logically group menu items. We will learn how to use the jpopupmenu class to provide support for the pop-up menu after the jmenu is selected, or any component environment. Similar to the abstract button, each menu element also has a shortcut key used for keyboard selection. We will also learn about the support for keyboard shortcuts, so that you can avoid traversing in a multi-level single dish.
In addition to menu-related components, this chapter describes the selected jmenubar model and the specific event-related classes of the menu. The selected model interface we want to know is the singleselectionmodel interface, and its default defaultsingleselectionmodel. We will discuss menu-specific listeners, event menulistener/menuevent, menukeylistener/menukeyevent, and menudragmouselistener/menudragmouseevent. In addition, we will learn how to use popup and popupfactory to create other pop-up components and use the toolbar through the jtoolbar class.
6.1 use menu
Let's first look at an example of how menu components are combined. To start learning, create a form with a menu bar, as shown in 6-1.
This simple menu example has the following features:
- On the menu bar, there are two common menus: file and edit. Under the File menu, we are familiar with new, open, close, and exit. Under the edit menu, it is the cut, copy, paste and find Sub-menus and a find option. The option sub-menu will contain the search direction sub-menu -- forward and backward -- and a case-sensitive switch.
- In different menu locations, menu delimiters divide options into logical sets.
- Each menu option has an associated hotkey, which allows you to browse and select the keyboard. The hot key allows you to select a menu through the keyboard. For example, you can press Alt-F on Windows to open the File menu.
- In addition to keyboard hotkeys, the keys associated with multiple options can be used as keyboard shortcuts. Unlike the hotkey, the shortcut key can directly activate a menu option, even if the menu option is not visible.
- The option sub-menu has an icon associated with it. Although only one icon is displayed in Figure 6-1, all menu components can have one icon, except the jaggregator and jpopupmenu components.
Note: For this example, these menu options will not do anything meaningful, but only the menu options to be output will be selected. For example, if the copy option is selected from the edit menu, selected: copy is displayed.
LIST 6-1 shows the complete code of the sample class generated in Figure 6-1.
/** * */package net.ariel.ch06; import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent; import javax.swing.ButtonGroup;import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JCheckBoxMenuItem;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JRadioButtonMenuItem;import javax.swing.KeyStroke; /** * @author mylxiaoyi * */public class MenuSample { static class MenuActionListener implements ActionListener {public void actionPerformed(ActionEvent event ) {System.out.println("Selected: "+event.getActionCommand());}}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubRunnable runner = new Runnable() {public void run() {MenuActionListener menuListener = new MenuActionListener();JFrame frame = new JFrame("Menu Sample");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File");fileMenu.setMnemonic(KeyEvent.VK_F);menuBar.add(fileMenu); JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);newMenuItem.addActionListener(menuListener);fileMenu.add(newMenuItem); JMenuItem openMenuItem = new JMenuItem("Open", KeyEvent.VK_O);openMenuItem.addActionListener(menuListener);fileMenu.add(openMenuItem); JMenuItem closeMenuItem = new JMenuItem("Close", KeyEvent.VK_C);closeMenuItem.addActionListener(menuListener);fileMenu.add(closeMenuItem); fileMenu.addSeparator(); JMenuItem saveMenuItem = new JMenuItem("Save", KeyEvent.VK_S);saveMenuItem.addActionListener(menuListener);fileMenu.add(saveMenuItem); fileMenu.addSeparator(); JMenuItem exitMenuItem = new JMenuItem("Exit", KeyEvent.VK_X);exitMenuItem.addActionListener(menuListener);fileMenu.add(exitMenuItem); JMenu editMenu = new JMenu("Edit");editMenu.setMnemonic(KeyEvent.VK_E);menuBar.add(editMenu); JMenuItem cutMenuItem = new JMenuItem("Cut", KeyEvent.VK_T);cutMenuItem.addActionListener(menuListener);KeyStroke ctrlXKeyStroke = KeyStroke.getKeyStroke("control X");cutMenuItem.setAccelerator(ctrlXKeyStroke);editMenu.add(cutMenuItem); JMenuItem copyMenuItem = new JMenuItem("Copy", KeyEvent.VK_C);copyMenuItem.addActionListener(menuListener);KeyStroke ctrlCKeyStroke = KeyStroke.getKeyStroke("control C");copyMenuItem.setAccelerator(ctrlCKeyStroke);editMenu.add(copyMenuItem); JMenuItem pasteMenuItem = new JMenuItem("Paste", KeyEvent.VK_P);pasteMenuItem.addActionListener(menuListener);KeyStroke ctrlVKeyStroke = KeyStroke.getKeyStroke("control V");pasteMenuItem.setAccelerator(ctrlVKeyStroke);editMenu.add(pasteMenuItem); editMenu.addSeparator(); JMenuItem findMenuItem = new JMenuItem("Find", KeyEvent.VK_F);findMenuItem.addActionListener(menuListener);KeyStroke f3KeyStroke = KeyStroke.getKeyStroke("F3");findMenuItem.setAccelerator(f3KeyStroke);editMenu.add(findMenuItem); JMenu findOptionsMenu = new JMenu("Options");Icon atIcon = new ImageIcon("at.gif");findOptionsMenu.setIcon(atIcon);findOptionsMenu.setMnemonic(KeyEvent.VK_O); ButtonGroup directionGroup = new ButtonGroup(); JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true);forwardMenuItem.addActionListener(menuListener);forwardMenuItem.setMnemonic(KeyEvent.VK_F);findOptionsMenu.add(forwardMenuItem);directionGroup.add(forwardMenuItem); JRadioButtonMenuItem backMenuItem = new JRadioButtonMenuItem("Back");backMenuItem.addActionListener(menuListener);backMenuItem.setMnemonic(KeyEvent.VK_B);findOptionsMenu.add(backMenuItem);directionGroup.add(backMenuItem); findOptionsMenu.addSeparator(); JCheckBoxMenuItem caseMenuItem = new JCheckBoxMenuItem("Case Sensitive");caseMenuItem.addActionListener(menuListener);caseMenuItem.setMnemonic(KeyEvent.VK_C);findOptionsMenu.add(caseMenuItem);editMenu.add(findOptionsMenu); frame.setJMenuBar(menuBar);frame.setSize(350, 250);frame.setVisible(true); }};EventQueue.invokeLater(runner);} }
6.1.1 menu class hierarchy
Now we know how to create cascade menus for programs. We should have learned about the content involved in using the swing menu component. For clarity, Figure 6-2 shows how all swing menu components are associated internally.
The most important concept shown in Figure 6-2 is that all swing menu elements that are subclasses of jcomponent are AWT components. We can place the jmenuitem, jmenu, and jmenubar components where the AWT component can be placed, rather than on the form. In addition, because jmenuitem is inherited by abstractbutton, jmenuitem and its subclass inherit the support of various icons and HTML text labels, as described in chapter 5th.
In addition to being part of the basic class hierarchy, each menu component that can be selected implements the menuelement interface. This interface describes the menu actions required to support keyboard and mouse browsing. The predefined menu component has implemented this behavior, so we do not have to implement it ourselves. If you are more interested in how this interface works, see the "menuelement interface" section in this chapter.
Next, let's take a look at different swing menu components.
6.1.2 jmenubar class
The swing menu bar component is jmenubar. The operation requires that we use the jmenu element with the jmenuitem element to fill the menu bar. Then, we add the menu bar to the jframe or other user interface components that require the menu bar. The menu then depends on the help of singleselectionmodel to determine which jmenu is displayed or sent after it is selected.
Create a jmenubar component
Jmenubar has a non-parameter constructor: Public jmenubar (). Once the menu bar is created, you can use the japplet, jdialog, jframe, jinternalframe, or jrootpane setjmenubar () method to add it to a window.
JMenuBar menuBar = new JMenuBar();// Add items to it...JFrame frame = new JFrame("MenuSample Example");frame.setJMenuBar(menuBar);
You can use the setjmenubar () method to display the menu bar in the upper part of the form and the lower part of the form title (if any ). Other sensory types, such as the Macintosh aqua, place the menu bar elsewhere.
We can also use the add () method of container to add jmenubar to the window. When added using the add () method, jmenubar is managed through the iner layout manager.
After we have a jmenubar, we need to fill the menu bar with other menu classes.
Add and remove menus to and from the menu bar
We need to add the jmenu object to jmenubar. Otherwise, only the border with no content is displayed. There is only one way to add a menu to jmenubar:
Public jmenu add (jmenu menu)
By default, consecutive menus are displayed from left to right. This will make the first added menu the leftmost menu, and the last added menu the rightmost menu. The menus added between the two are displayed in the order they are added. For example, in the example program 6-1 in the list, the order of menu addition is as follows:
JMenu fileMenu = new JMenu("File");menuBar.add(fileMenu);JMenu editMenu = new JMenu("Edit");menuBar.add(editMenu);
In addition to the add () method of jmenubar, multiple overloaded add () methods inherited by container can be used to control the menu position. The most interesting method is the add (Component component, int index) method, which allows us to specify the display position of the new jmenu. The second add () method allows us to place the jmenu component of file and edit in different order in jmenubar, but the same result will be obtained:
menuBar.add(editMenu);menuBar.add(fileMenu, 0);
If we have added a jmenu component to jmenubar, we can use the remove (Component component) or remove (INT index) method inherited by the container to remove the menu:
bar.remove(edit);bar.remove(0);
Jmenubar attributes
Table 6-1 shows the 11 attributes of jmenubar. Half of the attributes are read-only, and only the current menu bar status can be queried. Other attributes allow us to modify the appearance of the menu bar by determining whether the border of the menu bar is drawn and selecting the blank size between menu elements. The selected Attribute and selectionmodel can control which menu is selected on the menu bar. When the selected component is set to a menu on the menu bar, the menu component is displayed in the window as a pop-up menu.
Jmenubar attributes
|
Attribute name |
Data Type |
Accessibility |
Accessiblecontext |
Accessiblecontext |
Read-Only |
Borderpainted |
Boolean |
Read/write |
Component |
Component |
Read-Only |
Helpmenu |
Jmenu |
Read-Only |
Margin |
Insets |
Read/write |
Menucount |
Int |
Read-Only |
Selected |
Boolean/component |
Read/write |
Selectionmodel |
Singleselectionmodel |
Read/write |
Subelements |
Menuelement [] |
Read-Only |
UI |
Menubarui |
Read/write |
Uiclassid |
String |
Read-Only |
Custom jmenubar View
Each predefined swing view provides a different appearance and a default set of uiresource values for jmenubar and menu components. Figure 6-3 shows the appearance of the menu components of the pre-installed visual type set: motif, windows, and ocean.
Considering the specific appearance of jmenubar, Table 6-2 shows a set of uiresource-related attributes. The jmenubar component has 12 attributes.
Jmenubar uiresource Element
|
Attribute string |
Object Type |
Menubar. actionmap |
Actionmap |
Menubar. Background |
Color |
Menubar. Border |
Border |
Menubar. bordercolor |
Color |
Menubar. darkshadow |
Color |
Menubar. Font |
Font |
Menubar. Foreground |
Color |
Menubar. Gradient |
List |
Menubar. Highlight |
Color |
Menubar. Shadow |
Color |
Menubar. windowbindings |
Object [] |
Menubarui |
String |
If we need a vertical menu bar instead of a horizontal menu bar, we simply need to change the layoutmanager of the menu bar component. For example, gridlayout in the zero row and one column can do this, as shown in the following example, the number of rows will increase infinitely due to the addition of jmenu:
import java.awt.*;import javax.swing.*;public class VerticalMenuBar extends JMenuBar { private static final LayoutManager grid = new GridLayout(0,1); public VerticalMenuBar() { setLayout(grid); }}
Move the menu bar shown in Figure 6-1 to the east of borderlayout and use verticalmenubar to replace jmenubar's result 6-4. Although the vertical menu bar does not look comfortable here, vertical stacking of menu items rather than horizontal stacking is required on the right side (or left side) of the window. However, we may need to modify the menubar. Border attribute to modify the border.
6.1.3 singleselectionmodel Interface
Singleselectionmodel describes an index as the data structure of an integer index, and its elements can be selected. The data structure behind the interface is similar to data or vector, where repeated access to the same location can get the same object. The singleselectionmodel interface is the selection model of jmenubar and jpopupmenu. In jmenubar, the interface describes the currently selected jmenu to be drawn. In jpopupmenu, the interface describes the currently selected jmenuitem.
The singleselectionmodel interface is defined as follows:
public interface SingleSelectionModel { // Listeners public void addChangeListener(ChangeListener listener); public void removeChangeListener(ChangeListener listener); // Properties public int getSelectedIndex(); public void setSelectedIndex(int index); public boolean isSelected(); // Other Methods public void clearSelection();}
As we can see, apart from selecting indexes, the interface needs to maintain a changelistener list to be notified when the selected index changes.
The default implementation of the singleselectionmodel provided by swing is the defaultsingleselectionmodel class. For jmenubar and jpopupmenu, we usually do not need to modify the Selection Model Obtained by its default implementation.
Defaultsingleselectionmodel manages a list of changelistener objects. In addition, the model uses-1 to identify that NO content is selected currently. When the selected index is-1, isselected () returns false; otherwise, this method returns true. When the selected index changes, the registered changelistener object will be notified.