Par de valores clave de cuadro combinado en JavaFX 2
Frecuentes
Visto 33,018 veces
21
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?
3 Respuestas
24
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
16
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
0
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 java javafx-2 or haz tu propia pregunta.
¿Has echado un vistazo a el tutorial sobre Combo Boxes? - assylias
@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. - Shrestha