AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79200593
Accepted
user1438038
user1438038
Asked: 2024-11-18 23:54:40 +0800 CST2024-11-18 23:54:40 +0800 CST 2024-11-18 23:54:40 +0800 CST

Ligação JavaFX para seleção de valor de combobox específico

  • 772

Minha interface tem dois campos de entrada: uma caixa de combinação para selecionar Countrye 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.

java
  • 3 3 respostas
  • 51 Views

3 respostas

  • Voted
  1. James_D
    2024-11-19T01:15:35+08:002024-11-19T01:15:35+08:00

    No JavaFX 19 e posteriores, você pode usar ObservableValue.map(...):

    var selectedCountryName = cmbCountry.getSelectionModel().selectedItemProperty().map(Country::getName);
    // or
    // var selectedCountryName = cmbCountry.valueProperty().map(Country::getName);
    var germanyNotSelected = selectedCountryName.map(country -> ! "Germany".equals(country)).orElse(true);
    cbxFreeShipping.disableProperty().bind(germanyNotSelected);
    

    O selectedCountryNameconterá nullse nada for selecionado (ou se a Countryinstância selecionada retornar nullde getName()).

    selectedCountryName.map(country -> ! "Germany".equals(country))será nullse selectedCountryNamefor nulo, e caso contrário conterá o resultado de !"Germany".equals(country). A orElse(true)chamada retorna um valor contendo truese selectedCountryNamecontém null.

    Aqui está um exemplo completo:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.CheckBox;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.ListCell;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class HelloApplication extends Application {
    
        static class Country {
            private final String name;
            Country(String name) {
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
        }
    
        @Override
        public void start(Stage stage)  {
            ComboBox<Country> cmbCountry = new ComboBox<>();
            cmbCountry.getItems().addAll(
                new Country("France"),
                new Country("Germany"),
                new Country("Spain")
            );
            cmbCountry.setCellFactory( _ -> createCountryCell());
            cmbCountry.setButtonCell(createCountryCell());
            CheckBox cbxFreeShipping = new CheckBox("Free Shipping");
            var selectedCountryName = cmbCountry.getSelectionModel().selectedItemProperty().map(Country::getName);
            var germanyNotSelected = selectedCountryName.map(country -> ! "Germany".equals(country)).orElse(true);
            cbxFreeShipping.disableProperty().bind(germanyNotSelected);
    
            VBox root = new VBox(5, cmbCountry, cbxFreeShipping);
            Scene scene = new Scene(root, 400, 400);
            stage.setScene(scene);
            stage.show();
        }
    
        private ListCell<Country> createCountryCell() {
            return new ListCell<>() {
                @Override
                protected void updateItem(Country item, boolean empty) {
                    super.updateItem(item, empty);
                    if (empty || item == null) {
                        setText(null);
                    } else {
                        setText(item.getName());
                    }
                }
            };
        }
    
        public static void main(String[] args) {
            launch();
        }
    }
    
    • 3
  2. Best Answer
    DaveB
    2024-11-19T00:36:59+08:002024-11-19T00:36:59+08:00

    É melhor usar Bindings.createBooleanBinding()apenas o ComboBox.valueProperty(). Então você pode simplesmente escrever um Supplierque avalia o valor atual de ComboBox.valueProperty()como um simples e anulável String.

    Isso é Kotlin, mas os conceitos são idênticos:

    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)
    

    O ponto-chave aqui é que na Bindings.createBinding()chamada, a dependência está no comboBox.valueProperty()significado de que o Bindingserá invalidado sempre que houver comboBox.valueProperty()alterações. Então o código no Supplierirá apenas olhar para comboBox.value, que é equivalente a comboBox.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 pegar Country.namecomo um ObservableValue. Mas então você precisará fazer cast ObservableStringValuepara usar a API Fluent, pois o mapeamento retornará um ObservableValue<String>. Não é difícil, mas a Bindings.createBooleanBinding()abordagem é mais limpa.

    • 2
  3. user1438038
    2024-11-19T18:28:08+08:002024-11-19T18:28:08+08:00

    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:

    BooleanBinding noFreeShipping = Bindings.createBooleanBinding(() -> {
        var noCountry = (null == cmbCountry.getValue());
        var isGermany = (null != cmbCountry.getValue() && "Germany".equals(cmbCountry.getValue().getName()));
    
        return (noCountry || !isGermany);
    }, cmbCountry.valueProperty());
    cbxFreeShipping.disableProperty().bind(noFreeShipping);
    

    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:

    var selectedCountryName = cmbCountry.valueProperty().map(Country::getName);
    var isNotGermany = selectedCountryName.map(country -> ! "Germany".equals(country)).orElse(true);
    cbxFreeShipping.disableProperty().bind(isNotGermany);
    

    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!

    • 0

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve