I recently tried to take advantage of the fact that you can use ComboBox.setValue() to set the value to an "item" that is not present in the ComboBox's model items. The ComboBox, however, has a custom ButtonCell and a CellFactory set because I want to display an icon with each model item. When I set the value to an item not in the model it displays in the ComboBox but not with my custom ButtonCell.
Run the provided test case (sorry its so large) and click on the "Set to Magenta" button to add in the foreign item. I did test using a "converter" and this does seem to work with foreign items but does not help me display an icon with each item.
*****************************************************************************
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ComboBoxTest extends Application {
@Override public void start(Stage primaryStage) throws Exception {
primaryStage.centerOnScreen();
primaryStage.setHeight(200);
primaryStage.setWidth(200);
final ComboBox<TestObject> combo = new ComboBox<>();
combo.setButtonCell(new CustomCell());
combo.setCellFactory(new Callback<ListView<TestObject>,
ListCell<TestObject>>() {
@Override public ListCell<TestObject> call(ListView<TestObject> param){
return new CustomCell();
}
});
// un comment this to see that the converter is being used but still
// not the right button cell.
// combo.setConverter(new StringConverter<TestObject>() {
// @Override public String toString(TestObject object) {
// return object.name_;
// }
// @Override public TestObject fromString(String string) {
// return null;
// }
// });
combo.getItems().addAll(
new TestObject("Red", Color.RED),
new TestObject("Green", Color.GREEN),
new TestObject("Blue", Color.BLUE) );
Button button = new Button("Set to Magenta");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
combo.setValue(new TestObject("Magenta", Color.MAGENTA));
}
});
primaryStage.setScene( new Scene( new VBox( 30, combo, button ) ) );
primaryStage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
private static class CustomCell extends ListCell<TestObject> {
private final Rectangle colorRect_ = new Rectangle(12, 12);
@Override protected void updateItem(TestObject item, boolean empty) {
super.updateItem(item, empty);
if ( item == null || empty ) {
setText(null);
setGraphic(null);
} else {
setText(item.name_);
colorRect_.setFill(item.color_);
setGraphic(colorRect_);
}
}
}
private static class TestObject extends Object {
private final Color color_;
private final String name_;
private TestObject(String name, Color color) {
name_ = name;
color_ = color;
}
}
}
Run the provided test case (sorry its so large) and click on the "Set to Magenta" button to add in the foreign item. I did test using a "converter" and this does seem to work with foreign items but does not help me display an icon with each item.
*****************************************************************************
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ComboBoxTest extends Application {
@Override public void start(Stage primaryStage) throws Exception {
primaryStage.centerOnScreen();
primaryStage.setHeight(200);
primaryStage.setWidth(200);
final ComboBox<TestObject> combo = new ComboBox<>();
combo.setButtonCell(new CustomCell());
combo.setCellFactory(new Callback<ListView<TestObject>,
ListCell<TestObject>>() {
@Override public ListCell<TestObject> call(ListView<TestObject> param){
return new CustomCell();
}
});
// un comment this to see that the converter is being used but still
// not the right button cell.
// combo.setConverter(new StringConverter<TestObject>() {
// @Override public String toString(TestObject object) {
// return object.name_;
// }
// @Override public TestObject fromString(String string) {
// return null;
// }
// });
combo.getItems().addAll(
new TestObject("Red", Color.RED),
new TestObject("Green", Color.GREEN),
new TestObject("Blue", Color.BLUE) );
Button button = new Button("Set to Magenta");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
combo.setValue(new TestObject("Magenta", Color.MAGENTA));
}
});
primaryStage.setScene( new Scene( new VBox( 30, combo, button ) ) );
primaryStage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
private static class CustomCell extends ListCell<TestObject> {
private final Rectangle colorRect_ = new Rectangle(12, 12);
@Override protected void updateItem(TestObject item, boolean empty) {
super.updateItem(item, empty);
if ( item == null || empty ) {
setText(null);
setGraphic(null);
} else {
setText(item.name_);
colorRect_.setFill(item.color_);
setGraphic(colorRect_);
}
}
}
private static class TestObject extends Object {
private final Color color_;
private final String name_;
private TestObject(String name, Color color) {
name_ = name;
color_ = color;
}
}
}