2012-05-22 39 views
15

我剛開始學習JavaFX 2.
現在我正在嘗試構建一個示例應用程序。然後我被困在組合框中。
我沒有在JavaFX中找到任何關於組合框鍵值對的參考。
http://docs.oracle.com/javafx/2/api/index.html上的組合框javadoc並沒有多說關鍵值對。JavaFX中的組合鍵值對2

如何創建具有不同顯示值和實際值的項目的組合框?

+0

你有沒有看過[組合框教程](http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm)? – assylias

+0

@assylias - 是的,我做到了。它沒有提及用鍵值對創建組合框的任何事情,只是一個簡單的組合框,其中包含一些項目。 –

回答

17

你有兩種方法:
1.簡單地覆蓋你的數據模型類中的toString()方法。示例:

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

請注意Employee類的overriden toString()。在這種情況下,組合框的鍵(實際值)將爲Employee實例,顯示值爲employee.toString()
2.第二種方法是設置組合框的cellFactory屬性。

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

該方法對單元格渲染提供了更強大的控制。你不能只是格式化顯示值,但也可以包括任何節點(控制)到單元格(在這種情況下,按鈕)並添加一些查看邏輯(item.getSalary()?「」:「」)。實際值保持不變,即員工實例。

+0

非常感謝您的回答。這正是我正在尋找的。我對它做了一些小改動,以便顯示像普通組合框這樣的項目,而不是在列表中有按鈕 –

+0

如果我們使用散列表作爲我們的鍵值對,這看起來如何?它會使用笨拙的'public void changed(ObservableValue <?extends Map > arg0,Map arg1,Map arg2){}'? –

10

還有另一種解決方案,實施StringConverter。這是非常有用的對象:

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

}

轉換器實現:

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

}在視圖

代碼:

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

要得到的值產品,你可以調用的getValue()方法:

cboProductos.getValue() 
+3

英文將有幫助! –

0

我知道這個問題是舊的,但因爲我花了很多時間在無意義的挖掘在這個問題上它是​​一種強制性的讓我分享成果。看起來,帶有overriden toString()方法的ComboBox即使在列表中存在重複字符串的情況下也可以將字符串解析回恰到好處的對象。分辨率必須基於索引,toString()僅用於演示。