One of the missing features of JavaFX in the 2.0 release was a ComboBox control, and I’m very pleased to say that we’ll be filling this gap in JavaFX 2.1. Indeed, it is already in the developer preview builds we’re putting out, and has been sitting in the OpenJFX mercurial repo for some weeks now. I’m fortunate enough to even be getting bug reports filed in our Jira issue tracker, which is justification enough to be getting early developer preview releases out into your hands as early as we have!
In the screenshot above you can see what the default ComboBox looks like. On the left you can see three non-editable ComboBox controls, and on the right you see three editable ComboBox controls. The default width of a ComboBox is based on the width of the content of the ComboBox, so that the menu appears as roughly the same width. You’ll note that the bottom-left ComboBox has a different font – this is because this ComboBox has a cell factory set on it, which is something I’ll cover shortly.
A quick detour: What is ComboBoxBase?
The ComboBox control is an extension of the ComboBoxBase class. For most developers this distinction is unnecessary, but for those of you wanting to write your own ComboBox-like control (which I hope is many 🙂 ), the following is worth reading. The ComboBoxBase class is an abstract class, whose goal is to represent the core concept of what a combo box is. ComboBoxBase brings the basic API expected across all combo box implementations. Firstly, it has a value property, which represents either the latest selection the user has made, or the latest input they have provided in the case of editable combo boxes. It also has the show() and hide() methods you would expect. The third key piece of API is the editable property, which specifies whether the ComboBox should allow user input. There is other API also, but what I’ve mentioned here is the core of it.
As mentioned above, ComboBoxBase is intended to represent the nature of all combo boxes – that is, a combo box is generically a button that, when clicked or otherwise prompted, shows to the user a number of choices. Examples of other, ComboBox-like controls include calendar pickers and colour choosers, but even extends to use cases where entire dialogs are popped-up on clicking. The ComboBoxBase does not pretend to know what happens when show() and hide() are called, and that is left up to subclasses whose skin extends the abstract ComboBoxBaseSkin class. For more information, refer to the ComboBox class and its ComboBoxListViewSkin skin class in OpenJFX. If all else fails, leave a comment on this post or email me with your questions.
To cement what I mean in the above two paragraphs, the ComboBox class extends ComboBoxBase to provide the most commonly used ComboBox form, which is the kind that displays a popup list from which a user may choose one option. You can see what the popup list looks like in ComboBox in the screenshot below.
The ComboBox control in JavaFX 2.1 has a very familiar API to anyone who has built user interfaces in JavaFX 2.0. It brings with it API from ListView, Button, ChoiceBox, and even a little bit of TextField. For example, ComboBox borrows from ListView (as well as TableView and ChoiceBox) the concept of having an items list that contains all elements to show to the user. The generic type of the ComboBox represents the type of the items list. In addition to this, ComboBox has a cell factory using exactly the same API (including ListCell) as the ListView control. This is why in the first screenshot above you see the bottom-left button has a different font – it is actually Cooper Black, as the bottom-left ComboBox has been populated with the fonts found on my computer. What this means is that the cell factory is used not just for the popup list, but it is also used in the ComboBox ‘button’ itself. Check out the screenshot below to understand better.
Another very useful addition to the ComboBox API (and one which has been retrofitted into the ChoiceBox API as well) is the support for StringConverter implementations (which in reality deserves its own blog post to detail the availability of the javafx.util.converter package and the ability to use these converters in the binding API as of JavaFX 2.1. Maybe Michael Heinrichs might cover this, *hint* 🙂 ). A StringConverter does exactly what the name suggests: it has two methods, one that takes an Object and returns a String, and the other that takes a String and attempts to return an Object. StringConverter implementations are therefore used within ComboBox for two purposes. Firstly, the ComboBox items list (and the text on the ComboBox button), when displayed to the user, is run through the StringConverter before being displayed. Secondly, it takes the commited text input and attempts to convert it to a object that can then be set in the value property.
The ComboBox makes use of the familiar SelectionModel API that is present in a number of other controls such as ListView, TreeView, TableView, ChoiceBox, TabPane, etc, and it works in the same way. One important point to note is that the ComboBox selection model is a SingleSelectionModel, so the ComboBox control will only ever support single selection. A future, separate control (e.g. ListBox or similar) might support multiple selection.
Hopefully with this post you’ll have a better understanding of what the ComboBox in JavaFX 2.1 can do. If you have any questions, please leave a comment on this post. If you find a bug, please file it in Jira.