Minha interface tem dois campos de entrada: uma caixa de combinação para selecionar Country
e uma caixa de seleção.
public class Country {
private String name;
public String getName() {
return name;
}
}
Quero apenas habilitar a caixa de seleção, caso um valor específico seja selecionado na caixa de combinação (por exemplo 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));
A primeira ligação por si só funciona bem, mas não consigo descobrir como fazer a segunda ligação depender de uma propriedade String dos itens do combobox. Tentei uma abordagem diferente implementando um listener no combobox, mas é claro que ele só dispara quando o item selecionado muda.
No JavaFX 19 e posteriores, você pode usar
ObservableValue.map(...)
:O
selectedCountryName
conteránull
se nada for selecionado (ou se aCountry
instância selecionada retornarnull
degetName()
).selectedCountryName.map(country -> ! "Germany".equals(country))
seránull
seselectedCountryName
for nulo, e caso contrário conterá o resultado de!"Germany".equals(country)
. AorElse(true)
chamada retorna um valor contendotrue
seselectedCountryName
contémnull
.Aqui está um exemplo completo:
É melhor usar
Bindings.createBooleanBinding()
apenas oComboBox.valueProperty()
. Então você pode simplesmente escrever umSupplier
que avalia o valor atual deComboBox.valueProperty()
como um simples e anulávelString
.Isso é Kotlin, mas os conceitos são idênticos:
O ponto-chave aqui é que na
Bindings.createBinding()
chamada, a dependência está nocomboBox.valueProperty()
significado de que oBinding
será invalidado sempre que houvercomboBox.valueProperty()
alterações. Então o código noSupplier
irá apenas olhar paracomboBox.value
, que é equivalente acomboBox.valueProperty().getValue()
, que é apenas uma String (anulável).Você pode fazer isso com a API Fluent, mas então você precisará usar
ObservableValue.map()
para pegarCountry.name
como umObservableValue
. Mas então você precisará fazer castObservableStringValue
para usar a API Fluent, pois o mapeamento retornará umObservableValue<String>
. Não é difícil, mas aBindings.createBooleanBinding()
abordagem é mais limpa.Para completar, gostaria de adicionar as duas soluções que foram enviadas até agora e que testei. Primeiro, ambas as abordagens funcionam! Já que @DaveB postou o código Kotlin, aqui está um equivalente Java:
Na minha opinião, essa implementação é mais fácil de ler e entender.
A solução enviada por @James_D também funciona e é um pouco mais curta:
No entanto, parece um pouco mais difícil de ler para mim, devido à natureza de
map()
. Além disso, o caso em que nenhum país é selecionado não é tão explícito. Não tenho certeza de qual solução é melhor do ponto de vista técnico, mas acho que vou ficar com a primeira implementação. - No entanto, aprecio as duas respostas!