An implementation of the ComboBoxBase
abstract class for the most common
form of ComboBox, where a popup list is shown to users providing them with
a choice that they may select from. For more information around the general
concepts and API of ComboBox, refer to the ComboBoxBase
class
documentation.
On top of ComboBoxBase, the ComboBox class introduces additional API. Most
importantly, it adds an items
property that works in
much the same way as the ListView items
property. In other words, it is the content of the items list that is displayed
to users when they click on the ComboBox button.
The ComboBox exposes the valueProperty()
from
javafx.scene.control.ComboBoxBase
, but there are some important points
of the value property that need to be understood in relation to ComboBox.
These include:
javafx.scene.control.SelectionModel.clearSelection()
in the selection model does not null the value
property - it remains the same as before.SelectionModel.selectedItemProperty()
and
value property will be updated to have this value. This is inconsistent with
other controls that use a selection model, but done intentionally for ComboBox.By default, when the popup list is showing, the maximum number of rows
visible is 10, but this can be changed by modifying the
visibleRowCount
property. If the number of
items in the ComboBox is less than the value of visibleRowCount
,
then the items size will be used instead so that the popup list is not
exceedingly long.
As with ListView, it is possible to modify the
selection model
that is used,
although this is likely to be rarely changed. This is because the ComboBox
enforces the need for a javafx.scene.control.SingleSelectionModel
instance, and it is not likely that there is much need for alternate
implementations. Nonetheless, the option is there should use cases be found
for switching the selection model.
As the ComboBox internally renders content with a ListView, API exists in
the ComboBox class to allow for a custom cell factory to be set. For more
information on cell factories, refer to the Cell
and ListCell
classes. It is important to note that if a cell factory is set on a ComboBox,
cells will only be used in the ListView that shows when the ComboBox is
clicked. If you also want to customize the rendering of the 'button' area
of the ComboBox, you can set a custom ListCell
instance in the
button cell
property. One way of doing this
is with the following code (note the use of setButtonCell
:
Callback<ListView<String>, ListCell<String>> cellFactory = ...;
ComboBox comboBox = new ComboBox();
comboBox.setItems(items);
comboBox.setButtonCell(cellFactory.call(null));
comboBox.setCellFactory(cellFactory);
Because a ComboBox can be editable
, and the
default means of allowing user input is via a TextField
, a
string converter
property is provided to allow
for developers to specify how to translate a users string into an object of
type T, such that the value
property may contain it.
By default the converter simply returns the String input as the user typed it,
which therefore assumes that the type of the editable ComboBox is String. If
a different type is specified and the ComboBox is to be editable, it is
necessary to specify a custom StringConverter
.
Node
instances. Putting nodes into
the items list is strongly not recommended. This is because
the default cell factory
simply inserts Node
items directly into the cell, including in the ComboBox 'button' area too.
Because the scenegraph only allows for Nodes to be in one place at a time,
this means that when an item is selected it becomes removed from the ComboBox
list, and becomes visible in the button area. When selection changes the
previously selected item returns to the list and the new selection is removed.
The recommended approach, rather than inserting Node instances into the
items list, is to put the relevant information into the ComboBox, and then
provide a custom cell factory
. For example,
rather than use the following code:
ComboBox<Rectangle> cmb = new ComboBox<Rectangle>();
cmb.getItems().addAll(
new Rectangle(10, 10, Color.RED),
new Rectangle(10, 10, Color.GREEN),
new Rectangle(10, 10, Color.BLUE));
You should do the following:
ComboBox<Color> cmb = new ComboBox<Color>();
cmb.getItems().addAll(
Color.RED,
Color.GREEN,
Color.BLUE);
cmb.setCellFactory(new Callback<ListView<Color>, ListCell<Color>>() {
@Override public ListCell<Color> call(ListView<Color> p) {
return new ListCell<Color>() {
private final Rectangle rectangle;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
rectangle = new Rectangle(10, 10);
}
@Override protected void updateItem(Color item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
rectangle.setFill(item);
setGraphic(rectangle);
}
}
};
}
});
Admittedly the above approach is far more verbose, but it offers the required functionality without encountering the scenegraph constraints.
extends
<T> | The type of the value that has been selected or otherwise entered in to this ComboBox |
ComboBoxBase, Cell, ListCell, StringConverter