My interface has two input fields: A combobox to select a Country
and a checkbox.
public class Country {
private String name;
public String getName() {
return name;
}
}
I just want to enable the checkbox, if a specific value is selected in the combobox (e.g. Germany
).
BooleanBinding noCountryBinding = Binding.isNull(cmbCountry.valueProperty());
BooleanBinding isGermanyBinding = Binding.equal(cmbCountry.getSelectionModel().selectedProperty().get().getName(), "Germany"); // <- This does not work, what can I do instead?
cbxFreeShipping.disableProperty().bind(Bindings.or(noCountryBinding, Bindings.not(isGermanyBinding));
The first binding on its own works fine, but I cannot figure out how to make the second binding rely on a String property of the combobox items. I tried a different approach by implementing a listener on the combobox, but of course it only triggers when the selected item changes.
You're best off using Bindings.createBooleanBinding()
using just the ComboBox.valueProperty()
. Then you can just write a Supplier
that evaluates the current value of ComboBox.valueProperty()
as a simple, nullable String
.
This is Kotlin, but the concepts are identical:
class ComboBoxExample0 : Application() {
private val countries = FXCollections.observableArrayList(
Country("Germany"),
Country("France"), Country("Denmark")
)
override fun start(stage: Stage) {
val scene = Scene(createContent(), 280.0, 300.0)
stage.scene = scene
stage.show()
}
private fun createContent(): Region = VBox(20.0).apply {
val comboBox = ComboBox<Country>().apply {
items = countries
}
children +=
CheckBox("This is a CheckBox").apply {
disableProperty().bind(
Bindings.createBooleanBinding(
{ (comboBox.value == null) || (comboBox.value.name == "Germany") },
comboBox.valueProperty()
)
)
}
children += comboBox
padding = Insets(40.0)
}
}
data class Country(val name: String)
fun main() = Application.launch(ComboBoxExample0::class.java)
The key point here being that in the Bindings.createBinding()
call, the dependency is on comboBox.valueProperty()
meaning that the Binding
will be invalidated whenever comboBox.valueProperty()
changes. Then the code in the Supplier
will just look at comboBox.value
, which is equivalent to comboBox.valueProperty().getValue()
, which is just a (nullable) String.
You can do it with the Fluent API, but then you'll need to use ObservableValue.map()
to grab Country.name
as an ObservableValue
. But then you'll need to cast it to ObservableStringValue
in order to use the Fluent API, as the mapping will return an ObservableValue<String>
. It's not difficult, but the Bindings.createBooleanBinding()
approach is cleaner.