2012-05-22 19 views
15

Estoy empezando a aprender JavaFX 2.
Ahora intento crear una aplicación de muestra. Luego me quedé atrapado en el combobox.
No encontré ninguna referencia al par de valores clave para combobox en JavaFX.
el Javadoc cuadro combinado en http://docs.oracle.com/javafx/2/api/index.html no dice mucho sobre el par de valores clave.Par de valores clave combinados en JavaFX 2

¿Cómo puedo crear un cuadro combinado que tiene elementos que tienen diferente valor indicado y el valor real?

+0

¿Ha tenido un vistazo a [el tutorial en los cuadros combinados] (http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm)? – assylias

+0

@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. –

Respuesta

17

Tienes 2 enfoques:
1. Simplemente reemplazar el método toString() 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 que overriden toString() de la clase Employee. clave (valor real) del cuadro combinado será el Employee instancia y al valor de visualización 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 proporciona un control más poderoso sobre la representación de células. No puede simplemente 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, instancia de empleado.

+0

Muchas gracias por su respuesta. Era lo que estaba buscando. Hice un pequeño cambio a él para que muestre elementos como un cuadro combinado normal, en lugar de tener botones en la lista –

+0

¿Cómo se vería esto si estábamos usando un HashMap para nuestro par clave-valor? ¿Utilizaría el poco manejable 'void público cambiado (ObservableValue > arg0, Map arg1, Map arg2) {}'? –

10

Hay otra solución, la implementación de un StringConverter. Es muy útil para los objetos:

public class Producto { 

private String codigo; 
private String nombre; 

public Producto(String codigo, String nombre) { 
    this.codigo = codigo; 
    this.nombre = nombre; 
} 

public String getCodigo() { 
    return codigo; 
} 

public void setCodigo(String codigo) { 
    this.codigo = codigo; 
} 

public String getNombre() { 
    return nombre; 
} 

public void setNombre(String nombre) { 
    this.nombre = nombre; 
} 

}

aplicación Convertidor:

public class ProductoConverter extends StringConverter<Producto> { 

/** Cache de productos */ 
private Map<String, Producto> mapProductos = new HashMap<String, Producto>(); 

@Override 
public String toString(Producto producto) { 
    mapProductos.put(producto.getCodigo(), producto); 
    return producto.getNombre(); 
} 

@Override 
public Producto fromString(String codigo) { 
    return mapProductos.get(codigo); 
} 

} Código

el paisaje:

ComboBox<Producto> cboProductos = new ComboBox<Producto>; 
    cboProductos.setConverter(new ProductoConverter()); 
    cboProductos.getItems().addAll(serviciosMgr.getListaProductos()); 

para obtener el valor de la producto, puede llamar getValue) método (:

cboProductos.getValue() 
+3

¡Inglés sería útil! –

0

Sé que esta pregunta es viejo, sino porque me acaba de pasar horas en la excavación sin sentido en este tema es una especie de obligatoria para mí compartir los resultados. Parece que el ComboBox con el método overriden toString() resuelve las cadenas de regreso a los objetos correctos, incluso si hay cadenas duplicadas en la lista. La resolución debe basarse en el índice y toString() solo se usa para la presentación.

Cuestiones relacionadas