Par de valores clave de cuadro combinado en JavaFX 2

Estoy empezando a aprender JavaFX 2.
Ahora estoy tratando de construir una aplicación de muestra. Luego me quedé atascado en el cuadro combinado.
No encontré ninguna referencia al par de valores clave para el cuadro combinado en JavaFX.
El combobox javadoc en http://docs.oracle.com/javafx/2/api/index.html no dice mucho sobre el par de valores clave.

¿Cómo puedo crear un cuadro combinado que tenga elementos que tengan un valor de visualización y un valor real diferentes?

preguntado el 22 de mayo de 12 a las 10:05

¿Has echado un vistazo a el tutorial sobre Combo Boxes? -

@assylias - Sí, lo hice. No menciona nada sobre la creación de un cuadro combinado con un par de valores clave, solo un cuadro combinado simple con algunos elementos. -

3 Respuestas

Tienes 2 enfoques:
1. Simplemente anule el toString() método en su clase de modelo de datos. Ejemplo:

public class Demo extends Application {

    private final ObservableList<Employee> data =
            FXCollections.observableArrayList(
            new Employee("Azamat", 2200.15),
            new Employee("Veli", 1400.0),
            new Employee("Nurbek", 900.5));

    @Override
    public void start(Stage primaryStage) {

        ComboBox<Employee> combobox = new ComboBox<>(data);
        combobox.getSelectionModel().selectFirst(); // Select first as default
        combobox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Employee>() {

            @Override
            public void changed(ObservableValue<? extends Employee> arg0, Employee arg1, Employee arg2) {
                if (arg2 != null) {
                    System.out.println("Selected employee: " + arg2.getName());
                }
            }
        });
        StackPane root = new StackPane();
        root.getChildren().add(combobox);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

    public static class Employee {
        private String name;
        private Double salary;

        @Override
        public String toString() {
            return name + " (sal:" + salary + ")";
        }

        public Employee(String name, Double salary) {
            this.name = name;
            this.salary = salary;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Double getSalary() {
            return salary;
        }

        public void setSalary(Double salary) {
            this.salary = salary;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Tenga en cuenta el toString() anulado de la clase Employee. La clave del cuadro combinado (valor real) será el Employee instancia y el valor de visualización es employee.toString() en este caso.
2. El segundo enfoque es establecer la propiedad cellFactory del cuadro combinado.

combobox.setCellFactory(new Callback<ListView<Employee>, ListCell<Employee>>() {

    @Override
    public ListCell<Employee> call(ListView<Employee> arg0) {
        return new ListCell<Employee>() {

            private final Button btn;
            {
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                btn = new Button();
            }

            @Override
            protected void updateItem(Employee item, boolean empty) {
                super.updateItem(item, empty);

                if (item == null || empty) {
                    setGraphic(null);
                } else {
                    btn.setStyle(item.getSalary() > 1000 ? "-fx-base:red" : "-fx-base: green");
                    btn.setText(item.getName() + "=" + item.getSalary());
                    setGraphic(btn);
                }
            }
        };
    }
});

Este enfoque brinda un control más poderoso sobre la representación de celdas. No solo puede formatear el valor de visualización, sino también incluir cualquier nodo (control) en la celda (botón en este caso) y agregar alguna lógica de visualización (item.getSalary()?"":"") también. El valor real sigue siendo el mismo, es decir, la instancia de empleado.

respondido 26 mar '17, 11:03

Muchas gracias por su respuesta. Era lo que estaba buscando. Le hice un pequeño cambio para que muestre elementos como un cuadro combinado normal en lugar de tener botones en la lista: Shrestha

¿Cómo se vería esto si estuviéramos usando un hashmap para nuestro par clave-valor? ¿Utilizaría el difícil de manejar? public void changed(ObservableValue<? extends Map<String, String>> arg0, Map<String, String> arg1, Map<String, String> arg2) {}? - Stevoisiak

Hay otra solución, implementar un Convertidor de cadenas. Es muy útil para objetos:

public class Product {

    private String code;
    private String name;

    public Product(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Implementación del convertidor:

public class ProductConverter extends StringConverter<Product> {

    /** Cache of Products */
    private Map<String, Product> productMap = new HashMap<String, Product>();

    @Override
    public String toString(Product product) {
        productMap.put(product.getName(), product);
        return product.getName();
    }

    @Override
    public Product fromString(String name) {
        return productMap.get(name);
    }

}

Código a la vista:

    ComboBox<Product> cboProducts  = new ComboBox<Product>;
    cboProducts.setConverter(new ProductConverter());
    cboProducts.getItems().addAll(serviceManager.getProductList());

Para obtener el valor del producto, puede llamar al método getValue():

cboProducts.getValue()

Respondido 18 Abr '18, 01:04

Sé que esta pregunta es antigua, pero debido a que pasé horas investigando sin sentido sobre este tema, es obligatorio para mí compartir los resultados. Parece que el ComboBox con el método anulado toString() resuelve las cadenas de nuevo en objetos correctamente, incluso si hay cadenas duplicadas en la lista. La resolución debe estar basada en índices y toString() se usa solo para presentaciones.

Respondido 10 ago 14, 09:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.