FX Experience Has Gone Read-Only

I've been maintaining FX Experience for a really long time now, and I love hearing from people who enjoy my weekly links roundup. One thing I've noticed recently is that maintaining two sites (FX Experience and JonathanGiles.net) takes more time than ideal, and splits the audience up. Therefore, FX Experience will become read-only for new blog posts, but weekly posts will continue to be published on JonathanGiles.net. If you follow @FXExperience on Twitter, I suggest you also follow @JonathanGiles. This is not the end - just a consolidation of my online presence to make my life a little easier!

tl;dr: Follow me on Twitter and check for the latest news on JonathanGiles.net.

Important Note: Menus (and related classes) are ‘preview’ API in JavaFX 1.3, which means that the API may (and most probably will) change in future releases. However, you’re welcome to make use of these preview controls in 1.3. Read on to learn how.

Up until the release of JavaFX 1.3 it was not possible to build proper menus that ‘popped’ out of the Stage, as one expects a menu to do. It was not until we were able to expose other functionality internally that creating proper menus became possible. As already warned, in JavaFX 1.3 menus are preview controls whilst we firm them up and get feedback from the community. In this post I wanted to outline the API, and what options you have for styling them using nothing more than CSS.

All Menu-related controls are, for JavaFX 1.3 at least, located in the com.javafx.preview.control package. This package is the staging ground for all preview controls in JavaFX 1.3, and includes menu-related controls, as well as ToolBar, TreeView, MenuButton and SplitMenuButton. We’ll be covering those separately.

A simple menu in JavaFX 1.3

A simple menu in JavaFX 1.3

Menus can be used in a number of different places, for example, attached to a MenuBar, contained within another Menu, shown when called programmatically (e.g. MenuButton), and used as context menus (although this should be achieved using PopupMenu rather than Menu). For all these use cases, your first port of call should be the Menu control. Menu may be populated with any type of Node, however, in general only subclasses of MenuItemBase or a Separator are used as items for a Menu. Examples of controls that subclass MenuItemBase include Menu, MenuItem, CheckMenuItem, RadioMenuItem and CustomMenuItem. CustomMenuItem is a very early preview control, but it is the best way of embedding other, miscellaneous Nodes inside a Menu. Separator, of course, is a new and final control in JavaFX 1.3.

Creating a Menu in JavaFX is simple. Here is some sample code that will create a ‘File’ menu, common in many applications:

[jfx]
Menu {
text: "File"
items: [
MenuItem {
text: "New"
graphic: ImageView { image: Image { url: "{__DIR__}new.png" } }
action: function() { textbox.text = ""; }
}
MenuItem {
text: "Open…"
graphic: ImageView { image: Image { url: "{__DIR__}open.png" } }
action: function() { println("Open") }
}
MenuItem {
text: "Save"
graphic: ImageView { image: Image { url: "{__DIR__}save.png" } }
action: function() { println("Save") }
}
MenuItem {
text: "Save As…"
graphic: ImageView { image: Image { url: "{__DIR__}save_as.png" } }
action: function() { println("Save As…") }
}

Separator { }

MenuItem {
text: "Exit"
graphic: ImageView { image: Image { url: "{__DIR__}exit.png" } }
action: function() { FX.exit(); }
}
]
}
[/jfx]

Note: Whilst MenuItems allow for an accelerator to be set (as shown in the first screenshot), this API is currently not hooked in to any event system within JavaFX 1.3. In a future release this will of course work as expected, and we’ll blog more about this then.

Sub-Menus
To have a submenu in a menu, you simply do add a Menu into the items sequence, and this can be repeated to whatever depth is necessary for your application. For example, here is a rather simple example of having one submenu:

[jfx]
Menu {
text: "Format"
items: [
CheckMenuItem {
text: "Word Wrap"
selected: bind wordWrap with inverse;
},

Menu {
text: "Font"
items: [
MenuItem { text: "Font 1" }
MenuItem { text: "Font 2" }
MenuItem { text: "Font 3" }
]
}
]
}
[/jfx]

CheckMenuItem and RadioMenuItem

CheckMenuItem and RadioMenuItem in JavaFX 1.3

CheckMenuItem and RadioMenuItem in JavaFX 1.3

As can be seen in the code example above, the first MenuItem is actually a CheckMenuItem, which means that it will draw a check mark to indicate to the user whether it is currently selected or not. You can see a screenshot of a selected CheckMenuItem to the right. As a developer, you can bind to the selected boolean to be informed when this property changes, and react accordingly.

The other important type is of course RadioMenuItem, which is normally used to allow for mutually-exclusive selection of a single item in a group. To do this, you should create a ToggleGroup and assign it to all RadioMenuItem’s in this group (and for those wondering, this is the precise reason why we broke the ToggleGroup API in JavaFX 1.3). For example, you could create a Menu with three RadioMenuItems belonging to a single group as such:

[jfx]
var fontGroup:ToggleGroup = ToggleGroup { }
Menu {
text: "Font"
items: [
RadioMenuItem { text: "Font 1", toggleGroup: fontGroup }
RadioMenuItem { text: "Font 2", toggleGroup: fontGroup }
RadioMenuItem { text: "Font 3", toggleGroup: fontGroup }
]
}
[/jfx]

Styling Menus using CSS

Menus as used in the Authoring Tool

Menus as used in the Authoring Tool

Menus, as with all controls in JavaFX, can be easily styled using CSS. To the right is a styled menu that is being used in the JavaFX Authoring Tool. Note that the gradient runs from the top of the menu to the very bottom, yet the selection gradient runs only from the top to the bottom of the currently selected menu item: this is trivial using CSS.

Because a Menu is made up of a lot of items, be sure to refer to the official JavaFX 1.3 CSS guide that is due soon – this will be the best way to understand all regions that can be styled in CSS. What follows below is a relatively brief introduction that illustrates how the Authoring Tool folks reskinned the menu as is shown to the right. In future posts we’ll dive into far more detail about styling all other aspects of the menu.

*.popup-menu {
    -fx-background-color:
        linear (0%,0%) to (0%,100%) stops (0%,#383838) (100%,#141414);
}

.menu {
    -fx-text-fill: #ffffff;
}

*.menu-item {
    -fx-text-fill: #ffffff;
}

I hope that this post gives a good introduction to the basics of creating menus in JavaFX 1.3, and styling them. In a future post we’ll dive more deeply into how to use menus in various use cases (i.e. as context menus), and as mentioned, look more deeply at styling a menu to more closely suit the needs of your software.