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.
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:
[jfx]
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"); } }
]
}
[/jfx]
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.
[jfx]
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"); } }
]
}
[/jfx]
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:
[jfx]
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"); } }
]
}
[/jfx]
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.
SplitMenu has a graphic attribute, but this cannot be bound to lastItem.graphic because a node can be added at most one content. There can be other tricks to achive this.
One suggestion about splitmenubuttons is about the button part. Now, it cannot be used as toggle button.
Another suggestion is to add a behavior like in the Xpicker of jfxtras. The vertical indicator of the splitmenubutton may advance next menuitem. At this scenario, of course, a back arrow should also provided. I found the current vertical scenario useless.
Also, all popups including ChoiceBox have some bugs. First, when you move the window, they keep their position. This is a bug in swing, but not in prism. And also, in swing, when in fullscreen mode, the popups are not working. Currently, prism has no support of fullscreen mode.
Hi Jonathan & team:
Keep the controls coming! Our application is getting better with every release of JavaFX.
We have started using the preview MenuButton control as well as the ChoiceBox. Unfortunately, both of them suffer from terrible flicker problems on Linux OS. The moment you move from one menu item to the other, the whole menu redraws which causes a bad flicker. This however does not happen on Windows.
Any suggestions on how to overcome this flicker? Our target runtime is Linux and we have hit a block!
Thanks!
Dhruva Ray