I have customized a combobox in order to add and remove an item in a combobox. Now I would bind my customized combobox, but it is not working and I don't understand what happen.
Here my sample example :
public class CbbxEditSuppr extends ComboBox<BoxItem> {
private TextField editor = null;
private ObservableList<BoxItem> items = null;
/**
* Constructeur.
*
* @param addedItems ObservableList<String>
* @param prefWidth double largeur préférée
*/
public CbbxEditSuppr(ObservableList<String> addedItems, final double prefWidth) {
// initialisation des attributs
editor = this.getEditor();
items = this.getItems();
this.setPrefWidth(prefWidth);
// initialisation du contenu de la cellule
this.setCellFactory(new Callback<ListView<BoxItem>, ListCell<BoxItem>>() {
@Override
public ListCell<BoxItem> call(ListView<BoxItem> p) {
final ListCell<BoxItem> cell = new ListCell<BoxItem>() {
@Override
protected void updateItem(BoxItem t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
setGraphic(t.getBtn());
setText(t.getItem());
} else {
setGraphic(null);
}
}
};
return cell;
}
});
// déininition du converter
this.setConverter(new StringConverter<BoxItem>() {
@Override
public String toString(BoxItem cbbx) {
if (cbbx == null) {
return null;
} else {
return cbbx.getItem();
}
}
@Override
public BoxItem fromString(String id) {
if (id != null) {
final BoxItem box = new BoxItem(id, items);
return box;
} else {
return null;
}
}
});
// permet de prendre en compte la touche ENTER, et ajouter des valeurs a la liste
this.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
public void handle(final KeyEvent event) {
if (event != null && event.getCode().equals(KeyCode.ENTER)) {
if (editor.getText().trim().length() > 0) {
addItem(editor.getText());
editor.clear();
}
} else if (event != null && event.getCode().equals(KeyCode.DOWN)) {
showPopUpMenu();
}
}
});
// propriétés editable et selection du premier element
this.setEditable(true);
/* ajout des valeurs a la liste d'items */
if (addedItems != null && addedItems.size() > 0) {
for (String stg : addedItems) {
if (stg != null) {
final BoxItem hbox = new BoxItem(stg, items);
items.add(hbox);
}
}
}
this.getSelectionModel().selectFirst();
}
private void showPopUpMenu(){
if (!this.isShowing()) {
this.show();
}
}
/**
* Ajoute un item à la liste
*
* @param stg String nom de l'item
*/
public void addItem(String stg) {
if (stg != null) {
items.add(new BoxItem(stg, items));
}
}
/**
* Retourne la description du contenu de la liste
*/
public String toString() {
final StringBuilder stgBuilder = new StringBuilder("[ ");
if (items != null && items.size() > 0) {
final BoxItem lastItem = items.get(items.size() - 1);
for (BoxItem item : items) {
if (item != null) {
stgBuilder.append(item.getItem());
if (!item.equals(lastItem)) {
stgBuilder.append(", ");
}
}
}
}
stgBuilder.append(" ]");
return stgBuilder.toString();
}
}
and
public class ComboboxSample extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
stage.setTitle("ComboBoxSample");
Scene scene = new Scene(new Group(), 450, 250);
CbbxEditSuppr cbboxLeft = new CbbxEditSuppr(FXCollections.observableArrayList(new ArrayList()), 200);
CbbxEditSuppr cbboxRight = new CbbxEditSuppr(FXCollections.observableArrayList(new ArrayList()), 200);
cbboxLeft.itemsProperty().bindBidirectional(cbboxRight.itemsProperty());
GridPane grid = new GridPane();
grid.setVgap(4);
grid.setHgap(10);
grid.setPadding(new Insets(5, 5, 5, 5));
grid.add(new Label("To: "), 0, 0);
grid.add(cbboxLeft, 1, 0);
grid.add(cbboxRight, 2, 0);
Group root = (Group) scene.getRoot();
root.getChildren().add(grid);
stage.setScene(scene);
stage.show();
}
}
When I add a value in the right combobox it is working but not in the left combobox. Do you have any advice please ?
The issue is that you "shadow" the
items
field. There are basically two properties calleditems
in your combo box subclass: one that you define and one you inherit. When you callitemsProperty()
you are getting the property wrapping the inheriteditems
, and you are binding to that. In your class implementation, you then refer to the shadowitems
field, which is not bound.You should remove the
items
field entirely from your class, and just refer to the inherited one by callinggetItems()
.For example, do