The MenuButton and SplitMenuButton controls

The MenuButton and SplitMenuButton controls

We recently discussed the new preview Menu control that is part of JavaFX 1.3. Another part of this release is a number of controls that make use of menus internally, and this post talks about two new preview controls that do just this: MenuButton and SplitMenuButton.

The MenuButton menu

The MenuButton menu

MenuButton
The MenuButton control is a button that, when clicked, does not perform any action other than show/hide a menu containing menu items. For this reason, unlike the normal JavaFX Button control, there is no action property that you can define. Instead, just like the Menu API itself, you’ll find an items sequence within which you can provide any type of Node, although we recommend that you stick to only inserting MenuItems into the sequence (and remember that there are some useful subclasses including RadioMenuItem, CheckMenuItem, and CustomMenuItem).

To create a MenuButton, you do the following:

MenuButton {
    text: "Show Menu"
    items: [
        MenuItem { text: "Btn 1", action: function() { println("Action 1"); } }
        MenuItem { text: "Btn 2", action: function() { println("Action 2"); } }
        Separator { }
        MenuItem { text: "Btn 3", action: function() { println("Action 3"); } }
    ]
}
The SplitMenuButton menu

The SplitMenuButton menu

SplitMenuButton
The SplitMenuButton operates very similarly to the MenuButton, but allows for a separate action to be assigned. To enable this, and to make it obvious to the user that this is a SplitMenuButton rather than a normal MenuButton, we use the common convention of showing a divider between the ‘action’ region and the ‘open menu’ region. The skin is divided into two physical regions, with one region responsible for firing the assigned action, and the other responsible for showing the popup menu.

The SplitMenuButton skin in JavaFX 1.3 uses the majority of the button to represent the ‘action region’, with only a smaller area used to represent the ‘open menu’ region. Of course, it isn’t necessary that the SplitMenuButton actually have any action assigned to it, but this would suggest that a MenuButton would be a better fit.

SplitMenuButton {
    text: "Default action"
    action: function() { println("Default Action Started"); }
    items: [
        MenuItem { text: "Btn 1", action: function() { println("Action 1"); } }
        MenuItem { text: "Btn 2", action: function() { println("Action 2"); } }
        MenuItem { text: "Btn 3", action: function() { println("Action 3"); } }
    ]
}

In many cases a SplitMenuButton has an action specified that is not available within the menu itself, and for that reason the SplitMenuButton does not automatically assign whatever was last selected in the menu to be the action should the action region be clicked. If you want this effect, it is possible by doing the following:

var btn = SplitMenuButton {
    text: bind if (btn.lastItem == null) "SplitMenuButton" else btn.lastItem.text
    action: bind btn.lastItem.action;
    items: [
        MenuItem { text: "Btn 1", action: function() { println("Action 1"); } }
        MenuItem { text: "Btn 2", action: function() { println("Action 2"); } }
        MenuItem { text: "Btn 3", action: function() { println("Action 3"); } }
    ]
}
A MenuButton with OpenVertically set to false

A MenuButton with OpenVertically set to false

OpenVertically
One property that is available on both MenuButton and SplitMenuButton is the openVertically property, which by default is true. This is used to indicate to the skins whether the menu popup should appear beneath the button, or to the side of the button. For example, if the menu button were in a vertical toolbar on the left edge of the application, you might change openVertically to false so that the popup will appear to the right of the MenuButton. A screenshot is shown to the right of a MenuButton with openVertically set to false.

So that’s a very quick overview of the new MenuButton and SplitMenuButton controls that we’re previewing in JavaFX 1.3. If you have any thoughts on these controls please either leave comments here or file bugs / RFE in the JavaFX Jira issue tracker.