2012-05-22 7 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

2つのアプローチがあります。
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()? "": "")を追加することもできます。実際の値は、Employeeインスタンスと同じです。

+0

ありがとうございます。それは私が探していたものでした。私は小さな変更を加えて、リストにボタンを表示するのではなく、通常のコンボボックスのようなアイテムを表示するようにしました。 –

+0

私たちのキーと値のペアにハッシュマップを使用していたのはどうでしょうか? ObservableValue(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()); 

の値を取得するには製品、

cboProductos.getValue() 
+3

英語が役に立ちます! –

0

が、私はこの質問が古いであることを知っているが、私はちょうどこの問題に無意味な掘削に時間を費やしたので、それは私が結果を共有するための必須の種類があります:あなたは()メソッドのgetValueを呼び出すことができます。オーバーライドされたtoString()メソッドを持つComboBoxは、文字列がリストに重複していても、文字列を正しいオブジェクトに戻します。解像度はインデックスベースでなければならず、toString()はプレゼンテーションにのみ使用されます。