2012-05-22 14 views
15

Ich lerne gerade JavaFX 2 zu lernen.
Jetzt versuche ich eine Beispielanwendung zu erstellen. Dann bin ich in Combobox stecken geblieben.
Ich habe keinen Verweis auf Schlüsselwertpaar für Combobox in JavaFX gefunden.
Die Combobox Javadoc bei http://docs.oracle.com/javafx/2/api/index.html sagt nicht viel über Schlüsselwertpaar.Combo-Box Schlüsselwertpaar in JavaFX 2

Wie kann ich eine Combobox erstellen, die Elemente mit unterschiedlichen Anzeigewerten und tatsächlichen Werten enthält?

+0

Haben Sie sich [das Tutorial zu Kombinationsboxen] (http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm) angesehen? – assylias

+0

@assylias - Ja, tat ich. Es wird nichts über das Erstellen einer Kombinationsbox mit Schlüsselwertpaar erwähnt, sondern nur eine einfache Kombinationsbox mit einigen Elementen. –

Antwort

17

Sie haben zwei Ansätze:
1. Überschreiben Sie einfach die toString()-Methode in Ihrer Datamodel-Klasse. Beispiel:

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); 
    } 
} 

Beachten Sie die overriden toString() der Employee-Klasse. Der Schlüssel der Combobox (tatsächlicher Wert) ist die Employee Instanz und der Anzeigewert ist in diesem Fall employee.toString().
2. Der zweite Ansatz besteht darin, die Eigenschaft cellFactory der Combobox zu setzen.

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); 
       } 
      } 
     }; 
    } 
}); 

Dieser Ansatz gibt eine leistungsfähigere Kontrolle über Cell Rendering. Sie können nicht nur den Anzeigewert formatieren, sondern auch einen beliebigen Knoten (Steuerung) in die Zelle einfügen (in diesem Fall die Schaltfläche) und eine Anzeigelogik hinzufügen (item.getSalary()? "": ""). Der tatsächliche Wert bleibt gleich, dh Mitarbeiterinstanz.

+0

Vielen Dank für Ihre Antwort. Es war das, wonach ich suchte. Ich habe eine kleine Änderung daran vorgenommen, so dass es Elemente wie eine normale Combobox anstelle von Schaltflächen in der Liste anzeigt. –

+0

Wie würde das aussehen, wenn wir eine Hash-Map für unser Schlüssel-Wert-Paar verwenden würden? Wird die unhandliche 'public void geändert (ObservableValue > arg0, Map arg1, Map arg2) {}'? –

10

Es gibt eine andere Lösung, die eine StringConverter implementiert. Es ist sehr nützlich für Objekte:

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; 
} 

}

Converter Implementierung:

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); 
} 

}

-Code im Blick:

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

Um den Wert der zu erhalten Produkt, Sie können getValue() -Methode aufrufen:

cboProductos.getValue() 
+3

Englisch wäre hilfreich! –

0

Ich weiß, dass diese Frage ist alt, aber da ich nur wenige Stunden zu diesem Thema in sinnlosen Graben verbrachte dann ist es eine Art Pflicht für mich die Ergebnisse zu teilen. Es scheint, dass die ComboBox mit der override toString() -Methode die Strings wieder auf Objekte genau richtig auflöst, auch wenn in der Liste String-Duplikate vorhanden sind. Die Auflösung muss indexbasiert sein und toString() wird nur für die Präsentation verwendet.

Verwandte Themen