I am trying to update the text in a combobox when an element is changed without reinitializing the items or the item.
Is there a way to bind the item's text to the displayed text?
Even if I use a Property
it seems the StringConverter ignores it, which is understandable, but I am wondering if there is a way to do a binding without reinitializing the item.
Here is the reinitialization solion: JavaFx: ComboBox editor's text , which i want to avoid.
Here is a simple code which you can verify:
public class MainStageController implements Initializable {
@FXML
private ComboBox<Hero> comboBox;
@FXML
private Button lvlUp;
@Override
public void initialize(URL location, ResourceBundle resources) {
comboBox.setConverter(new StringConverter<Hero>() {
@Override
public String toString(Hero hero) {
return hero.getName() + " - Level: " + hero.getLevel();
}
@Override
public Hero fromString(String string) {
return null;
}
});
lvlUp.setOnAction(event -> {
Hero value = comboBox.getValue();
value.levelProperty().setValue(value.getLevel() + 1);
});
Hero weakHero = new Hero("Ted", 1);
Hero averageHero = new Hero("Zed", 10);
Hero strongHero = new Hero("Med", 25);
lvlUp.disableProperty().bind(comboBox.valueProperty().isNull());
comboBox.setItems(FXCollections.observableArrayList(weakHero, averageHero, strongHero));
}
private static class Hero {
private String name;
private IntegerProperty level;
public Hero(String name, Integer level) {
this.name = name;
this.level = new SimpleIntegerProperty(level);
}
private String getName() {
return name;
}
private int getLevel() {
return level.get();
}
public IntegerProperty levelProperty() {
return level;
}
}
}
What I want: When I press Level up, update the text both in the displayed text and in the dropdown.
Is that possible?
I explained how to use an Extractor. Using a StringConverter, no listeners ....I am using JavaFX 8...
public class UpdateableComboBox extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Hero> heros
= FXCollections.observableArrayList((Hero param) -> new Observable[] { param.nameProperty(), param.levelProperty() });
heros.add(new Hero("Ted", 1));
heros.add(new Hero("Zed", 10));
heros.add(new Hero("Med", 25));
ComboBox<Hero> comboBox = new ComboBox<>();
comboBox.setPrefWidth(350);
comboBox.setItems(heros);
Button button = new Button("Level Up");
button.setOnAction(e -> {
Hero value = comboBox.getValue();
value.levelProperty().setValue(value.getLevel() + 1);
});
comboBox.setConverter(new StringConverter<Hero>() {
@Override
public String toString(Hero hero) {
return hero.getName() + " - Level: " + hero.getLevel();
}
@Override
public Hero fromString(String string) {
return null;
}
});
HBox hbox = new HBox(comboBox, button);
Scene scene = new Scene(hbox, 500, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private class Hero {
private StringProperty name = new SimpleStringProperty();
private IntegerProperty level = new SimpleIntegerProperty();
Hero(String name, int level){
this.name.set(name);
this.level.set(level);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty levelProperty() {
return this.level;
}
public final int getLevel() {
return this.levelProperty().get();
}
public final void setLevel(final int level) {
this.levelProperty().set(level);
}
}
}