Õ¾ÄÚËÑË÷: ÇëÊäÈëËÑË÷¹Ø¼ü´Ê
µ±Ç°Ò³Ãæ: ͼÊéÊ×Ò³ > SWT: The Standard Widget Toolkit

8.2 Classes Menu and MenuItem - SWT: The Standard Widget Toolkit

Previous Section  < Day Day Up >  Next Section

8.2 Classes Menu and MenuItem

8.2.1 Example

graphics/08inf03.gif

8.2.2 Menu and MenuItem Hierarchies

graphics/08inf04.gif

8.2.3 Menu Styles

Style

Description

SWT.BAR

Create a menu bar

SWT.DROP_DOWN

Create a drop-down menu

SWT.POP_UP

Create a pop-up menu

SWT.NO_RADIO_GROUP

Disable radio button behavior

SWT.LEFT_TO_RIGHT

Force the menu orientation to be left to right

SWT.RIGHT_TO_LEFT

Force the menu orientation to be right to left


8.2.4 Menu Events

Event

Description

SWT.Hide

The menu is being hidden

SWT.Show

The menu is being shown

SWT.Help

The user requested help for the menu


8.2.5 MenuItem Styles

Style

Description

SWT.PUSH

Creates a push button menu item

SWT.CHECK

Creates a check button menu item

SWT.RADIO

Creates a radio button menu item

SWT.SEPARATOR

Creates a separator menu item

SWT.CASCADE

Creates a cascade menu item


8.2.6 MenuItem Events

Event

Description

SWT.Selection

The menu item was selected

SWT.Arm

The menu item is drawn in the armed state

SWT.Help

The user requested help for the menu item


Menus are very common user interface elements used to display a list of choices. Menus are represented in SWT by the classes Menu and MenuItem.[9] Menus are not controls.[10]

[9] The fact that a single Menu class is used to create every kind of menu is another example of the "minimize the number of classes" design philosophy of SWT.

[10] It seems strange but menus in Windows are not modeled in the operating system as controls. This forced us to model SWT menus the same way. The alternative is the tedious, thankless, and error-prone task of providing an implementation of every method they would inherit from control.

There are three kinds of menus: Menu bars, also called main menus, are created using the SWT.BAR style and appear as part of the shell trimming[11] below the shell title. Drop-down menus,[12] sometimes called submenus or cascade menus, are created with the SWT.DROP_DOWN style. They are displayed when the user selects a menu item from the menu bar or an item from another menu that contains a drop-down indicator. Pop-up or context menus, created using the SWT.POP_UP style, are displayed when the user requests a menu in a control using the mouse or the keyboard.

[11] This is not true on the Macintosh where there is a single menu bar shared by all applications on the desktop.

[12] On many platforms, the operating system makes no distinction between drop-down and pop-up menus, allowing them to be used interchangeably in either role. Unfortunately, Motif does not allow this, forcing SWT to make the same distinction. The alternative would have been to violate the rule that operating system resources are acquired when a widget is created.

One way to think about the relationship between the different kinds of menus is to consider that menu bars and pop-up menus are always the root of a containment hierarchy, composed of drop-down menus. This containment hierarchy is displayed whenever the user clicks on a menu item in the menu bar or requests a context menu.

The MenuItem class is analogous to the Button and ToolItem classes, supporting similar creation styles and listeners. Like instances of the other "item" classes, menu items are automatically added when created and are positioned similarly in the children list of the parent, using the location constructor parameter. Menu items are removed from a menu when they are disposed.

Like ToolItem and Button, instances of the MenuItem class support text and images. They also support separators and cascade items. A cascade item is a menu item that allows a drop-down menu to appear. Cascade items display the drop-down indicator.

8.2.7 Menu Items That Behave Like Buttons

The MenuItem class supports styles and listeners similar to the ToolItem and Button classes. For example, check and radio menu items are provided using the styles SWT.CHECK and SWT.RADIO. Text and images, mnemonics, and enabling and disabling are supported using Button and ToolItem API naming conventions. Like buttons and tool items, menu items do not wrap their text or support more than one line of text. One interesting difference between MenuItem and the other "buttonlike" classes is that MenuItem supports accelerators and accelerator text.

setText(String string) Sets the text for the item. This string may include mnemonic characters but cannot include line delimiters. The special character '\t' separates the menu text from the accelerator text. Accelerator text is the string used to inform the user that the menu item can be triggered using a key sequence. On platforms that support accelerator text, the string that follows the '\t' character is presented to the user, often right-aligned in the menu. Note that setting the accelerator text does not actually install an accelerator key. This is done using setAccelerator(). Accelerator text allows the application program complete control over the string that is displayed in the menu item, independent of the accelerator keystroke that invokes it. See Specifying the Accelerator Text in the chapter The Keyboard for further discussion and examples.

getText() Returns the item text. This is an empty string if the item text has never been set or if the item is a separator.

setImage(Image image) Sets the item contents to an image.

getImage() Returns the item image. This is null if the image has never been set or if the item is a separator.

setEnabled(boolean enable) Enables or disables the item, depending on the boolean argument. A disabled item is not selectable in the user interface and draws using a grayed look.

getEnabled() Returns the enabled state of the item.

isEnabled() Returns true if the item is enabled and all ancestors are enabled, otherwise returns false. Ancestors of a menu item do not follow the regular parent-child definition. Rather, the ancestors are traced from the menu item to the menu of the cascade menu item. This process continues all the way to the root menu, which is a either a menu bar or a pop-up menu.

8.2.8 Menu Items That Behave Like Separators

Menu items with the style SWT.SEPARATOR are used to reserve space between items in a menu. Sometimes the space is simply left blank between the items or an "etched line" is drawn. Even on the same operating system, the menu separator look can change between releases.[13]

[13] This happened between the Jaguar and Panther releases of Macintosh OS X.

8.2.9 Menu Items That Show Other Menus

Menu items with the style SWT.CASCADE are used to connect menus together. When the user selects the menu item, a drop-down menu cascades into view. Drop-down menus are connected to the menu bar, pop-up menus, or other drop-down menus using setMenu().

setMenu(Menu menu) Sets the menu for the item, connecting the drop-down menu to the cascade item. The item must have been created with the style SWT.CASCADE and the menu with the style SWT.DROP_DOWN, or an IllegalArgumentException is thrown. Setting the menu to null disconnects the menu from the item.

getMenu() Returns the menu for the item. This value is null when no menu has been set into the item.

8.2.10 Menu Items with Accelerators

Accelerators are keyboard shortcuts that allow the user to invoke menu items using the keyboard instead of the mouse. The section Accelerators in the chapter The Keyboard describes accelerators in detail, so they will not be discussed here.

8.2.11 Main Menus

To create a main menu, you need to create a menu with the style SWT.BAR. You can create many different menu bars, but only one can be displayed at a time. The setMenuBar() method in class Shell is used to show the menu bar (see Setting the Menu Bar in the Class Shell).

The following example program creates a shell and a menu bar with the classic "File" and "Edit" menus:






public static void main(String[] args) {

    Display display = new Display();

    Shell shell = new Shell(display);

    Menu menuBar = new Menu(shell, SWT.BAR);

    shell.setMenuBar(menuBar);

    MenuItem fileItem = new MenuItem(menuBar, SWT.CASCADE);

    fileItem.setText("File");

    MenuItem editItem = new MenuItem(menuBar, SWT.CASCADE);

    editItem.setText("Edit");

    Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);

    fileItem.setMenu(fileMenu);

    String [] fileStrings = {"New", "Close", "Exit"};

    for (int i=0; i<fileStrings.length; i++) {

          MenuItem item = new MenuItem(fileMenu, SWT.PUSH);

          item.setText(fileStrings [i]);

    }

    Menu editMenu = new Menu(shell, SWT.DROP_DOWN);

    String [] editStrings = {"Cut", "Copy", "Paste"};

    editItem.setMenu(editMenu);

    for (int i=0; i<editStrings.length; i++) {

          MenuItem item = new MenuItem(editMenu, SWT.PUSH);

          item.setText(editStrings [i]);

    }

    shell.pack();

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


Although this example program is a good vehicle to show how menus and menu items are created and wired together, application programs that use menus generally do not create their menu items from an array of strings. This is because menu items, like tool items and buttons, need more properties than just text in order to be really useful in a program.

8.2.12 Pop-Up Menus

To create a pop-up menu, you create a menu with the style SWT.POP_UP. Pop-up menus can be displayed automatically by the control (using the method Control.setMenu()) when the user requests a menu or they can be displayed programmatically using the setVisible() method.

setVisible(boolean visible) Shows or hides the menu. If a location was not specified and the menu is being shown, it is displayed at the current mouse location.

To show a menu at a particular location, setLocation() is used.

setLocation(int x, int y) Sets the location of the menu. The x and y coordinates are in the coordinate system of the display.

setLocation(Point location) Sets the location of the menu using a point. This is equivalent to setLocation(location.x, location.y).

Note that if you are showing a pop-up menu using setVisible() and setLocation(), you need to show it at the right time and the right place. The mouse movements and keyboard sequence used to request a pop-up menu are platform-specific. If you guess wrong, your pop-up menus will frustrate the user. The easiest way to avoid this problem is to let SWT pop the menu up for you using Control.setMenu() or to implement the control event SWT.MenuDetect (see Detecting a Context Menu Request).

The following example creates a pop-up menu and assigns it to a list control.






public static void main(String[] args) {

    Display display = new Display();

    Shell shell = new Shell(display);

    List list = new List(shell, SWT.BORDER | SWT.V_SCROLL);

    list.setItems(new String [] {"A", "B", "C", "D"});

    list.setSize(200, 200);

    Menu menu = new Menu(shell, SWT.POP_UP);

    for (int i=0; i<8; i++) {

          MenuItem item = new MenuItem(menu, SWT.PUSH);

          item.setText("Item " + i);

    }

    list.setMenu(menu);

    shell.pack();

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


8.2.13 Index-Based Operations for Menus

Menus provide a number of index and location operations that allow application programs to query items and indices from a menu.

getItem(int index) Returns the item at the index, which is zero-based. If the index is out of range, IllegalArgumentException("Index out of bounds") is thrown.

getItemCount() Returns the number of items in the menu.

getItems() Returns the items in the menu. This is a copy of the array that is used to hold the items so that modifying this structure will not affect the menu.

indexOf(MenuItem item) Returns the zero-based index of the item in the menu. If the item is not found, –1 is returned.

8.2.14 Menu Events

SWT.Show (MenuEvent)

Table 8.1 shows the show event for Menu.

Table 8.1. Show Event

Untyped Event

Description

SWT.Show

The widget is becoming visible

Typed Event

Listener

Methods

MenuEvent

MenuListener (and MenuAdapter)

menuHidden(MenuEvent)

menuShown(MenuEvent)


The SWT.Show event (typed event MenuEvent) is sent whenever a pull-down or pop-up menu is shown. The happens when the user requests the menu or the application program makes the menu visible using setVisible(). Show events contain meaningful values in only the display, widget, and type fields.

The SWT.Show event for Menu is one of the most useful events in SWT. It is often used to run the application code that enables or disables menu items. Because it occurs just before a menu is shown, modifications to the menu, including adding and removing menu items, are not visible to the user. The real benefit of SWT.Show is that it allows you to keep the code that maintains menu item state in one place. Without this event, the code would need to be distributed throughout your application in order to keep the menu up to date as state changes within your program. This kind of distributed code is error-prone. Note that you cannot use this approach for pull-down menus whose items contain accelerators. When the user types an accelerator, the menu is not shown, so SWT.Show will not be sent.The main disadvantage of using SWT.Show to update your menus is that the state of every menu item needs to be calculated, even if it has not changed since the last time the menu was shown. This is true because the menu item state is not maintained elsewhere in your program. If the application code that computes this state is slow, the user will be forced to wait for the menu to appear. Slow menus make the entire application appear to be slow.

The following example program uses SWT.Show to enable and disable menu items that correspond to the selected items in a list. If an item is selected, it is enabled.






public static void main(String[] args) {

    Display display = new Display();

    Shell shell = new Shell(display);

    final List list =

        new List(shell, SWT.BORDER | SWT.MULTI);

    for (int i=0; i<8; i++) list.add("Item " + i);

    list.setSize(200, 200);

    final Menu menu = new Menu(shell, SWT.POP_UP);

    for (int i = 0; i < list.getItemCount(); i++) {

        MenuItem item = new MenuItem(menu, SWT.PUSH);

        item.setText(list.getItem(i));

    }

    list.setMenu(menu);

    menu.addListener(SWT.Show, new Listener() {

        public void handleEvent(Event event) {

            MenuItem[] items = menu.getItems();

            for (int i = 0; i < items.length; i++) {

                MenuItem item = items[i];

                item.setEnabled(list.isSelected(i));

            }

        }

    });

    shell.pack();

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


SWT.Hide (MenuEvent)

Table 8.2 shows the hide event for Menu.

Table 8.2. Hide Event

Untyped Event

Description

SWT.Hide

The widget is being hidden

Typed Event

Listener

Methods

MenuEvent

MenuListener (and MenuAdapter)

menuHidden(MenuEvent)

menuShown(MenuEvent)


The SWT.Hide event (typed event MenuEvent) is sent whenever the menu is hidden. The can happen when the user selects a menu item or dismisses the menu, or when the application program makes a menu invisible using setVisible(false). Hide events contain meaningful values in only the display, widget, and type fields.

SWT.Help (HelpEvent)

Table 8.3 shows the help event for Menu.

Table 8.3. Help Event

Untyped Event

Description

SWT.Help

The user requested help for a widget

Typed Event

Listener

Methods

HelpEvent

HelpListener

helpRequested(HelpEvent)


The SWT.Help event (typed event HelpEvent) is sent whenever the user asks for help in a widget. Typically, the <F1> key is used for help but some platforms, such as the Macintosh, have a dedicated Help key. If no help is found for the menu, the request is forwarded to the shell. Help events contain meaningful values in only the display, widget, and type fields.

8.2.15 MenuItem Events

SWT.Selection (SelectionEvent)

The SWT.Selection event (typed event SelectionEvent) is sent whenever the user selects a menu item with the mouse or the keyboard. The event fields relevant during a selection event for a menu item are as follows.

Public Fields of Class Event That Are Valid during SWT.Selection

Field

Description

stateMask

A bitwise OR of modifier masks, indicating the state of the keyboard when the item was selected


The following code fragment prints "Menu item selected" when an item is selected.






item.addListener(SWT.Selection, new Listener() {

    public void handleEvent(Event event) {

        System.out.println("Menu item selected");

    }

});


SWT.Arm (ArmEvent)

Table 8.4 shows the arm event for Menu.

Table 8.4. Arm Event

Untyped Event

Description

SWT.Arm

A menu item is drawn in the armed state

Typed Event

Listener

Methods

ArmEvent

ArmListener

widgetArmed(ArmEvent)


The SWT.Arm event (typed event ArmEvent) is sent whenever the user causes the menu item to draw highlighted but does not select the item. This can happen using either the mouse or the keyboard. Arm events contain meaningful values in only the display, widget, and type fields.

Using SWT.Arm to Update a Status Line

The SWT.Arm event is often used to show a short help message in the status line of a window while the user browses through menu items without selecting them. Used in this capacity, it provides functionality that is analogous to tool tips.

By itself, the SWT.Arm event is not particularly useful. It allows you to set the status line text when the item is armed but there is no obvious MenuItem event that can be used to clear the text when the user closes the last menu. Fortunately, the Menu event SWT.Hide can be used to do this. However, from inside the SWT.Hide event, it is not possible to tell the difference between a menu that is hidden because the user is dragging the mouse across the menu bar and the user closing the last menu on the menu bar. In the former case, the SWT.Hide from the menu happens before the SWT.Arm for the menu item. The solution is to use the Menu event SWT.Show to set the status line text, as well.

The following example program uses SWT.Arm to implement a simple menu status line.






public static void main(String[] args) {

    Display display = new Display();

    Shell shell = new Shell(display);

    FormLayout layout = new FormLayout();

    shell.setLayout(layout);

    final Label label = new Label(shell, SWT.BORDER);

    Listener armListener = new Listener() {

        public void handleEvent(Event event) {

            MenuItem item = (MenuItem) event.widget;

            label.setText(item.getText());

        }

    };

    Listener showListener = new Listener() {

        public void handleEvent(Event event) {

            Menu menu = (Menu) event.widget;

            MenuItem item = menu.getParentItem();

            if (item != null) {

                label.setText(item.getText());

            }

        }

    };

    Listener hideListener = new Listener() {

        public void handleEvent(Event event) {

            label.setText("");

        }

    };

    FormData labelData = new FormData();

    labelData.left = new FormAttachment(0);

    labelData.right = new FormAttachment(100);

    labelData.bottom = new FormAttachment(100);

    label.setLayoutData(labelData);

    Menu menuBar = new Menu(shell, SWT.BAR);

    shell.setMenuBar(menuBar);

    MenuItem fileItem = new MenuItem(menuBar, SWT.CASCADE);

    fileItem.setText("File");

    fileItem.addListener(SWT.Arm, armListener);

    MenuItem editItem = new MenuItem(menuBar, SWT.CASCADE);

    editItem.setText("Edit");

    editItem.addListener(SWT.Arm, armListener);

    Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);

    fileMenu.addListener(SWT.Hide, hideListener);

    fileMenu.addListener(SWT.Show, showListener);

    fileItem.setMenu(fileMenu);

    String[] fileStrings = { "New", "Close", "Exit" };

    for (int i = 0; i < fileStrings.length; i++) {

        MenuItem item = new MenuItem(fileMenu, SWT.PUSH);

        item.setText(fileStrings[i]);

        item.addListener(SWT.Arm, armListener);

    }

    Menu editMenu = new Menu(shell, SWT.DROP_DOWN);

    editMenu.addListener(SWT.Hide, hideListener);

    editMenu.addListener(SWT.Show, showListener);

    String[] editStrings = { "Cut", "Copy", "Paste" };

    editItem.setMenu(editMenu);

    for (int i = 0; i < editStrings.length; i++) {

        MenuItem item = new MenuItem(editMenu, SWT.PUSH);

        item.setText(editStrings[i]);

        item.addListener(SWT.Arm, armListener);

    }

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


The result of running this code with the "Copy" menu item selected is shown in Figure 8.4.

Figure 8.4.

graphics/08fig04.gif


SWT.Help (HelpEvent)

Table 8.5 shows the help event for MenuItem.

Table 8.5. Help Event

Untyped Event

Description

SWT.Help

The user requested help for a widget

Typed Event

Listener

Methods

HelpEvent

HelpListener

helpRequested(HelpEvent)


The SWT.Help event (typed event HelpEvent) is sent whenever the user asks for help in a widget. Typically, the <F1> key is used for help but some platforms, such as the Macintosh, have a dedicated Help key. If no help is found in the menu item, the request is forwarded to the menu. Help events contain meaningful values in only the display, widget, and type fields.

    Previous Section  < Day Day Up >  Next Section