2014-07-11 95 views
4

我想用这个来选择自定义组合框的值:演员串

import java.util.List; 
import javafx.application.Application; 
import static javafx.application.Application.launch; 
import static javafx.application.Application.launch; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.util.StringConverter; 

public class MainApp extends Application 
{ 

    public static void main(String[] args) 
    { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) 
    { 

     final ComboBox<ListGroupsObj> listGroups = new ComboBox(); 

     listGroups.setButtonCell(new GroupListCell()); 
     listGroups.setCellFactory(new Callback<ListView<ListGroupsObj>, ListCell<ListGroupsObj>>() 
     { 
      @Override 
      public ListCell<ListGroupsObj> call(ListView<ListGroupsObj> p) 
      { 
       return new GroupListCell(); 
      } 
     }); 

     listGroups.setEditable(true); 
     listGroups.setConverter.............. 

     // Insert Some data 
     ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Test"); 
     listGroups.getItems().addAll(ob); 
     ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Test2"); 
     listGroups.getItems().addAll(osb); 
     listGroups.setValue(ob); 

     // Display the selected Group 
     listGroups.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ListGroupsObj>() 
     { 

      @Override 
      public void changed(ObservableValue<? extends ListGroupsObj> arg0, ListGroupsObj arg1, ListGroupsObj arg2) 
      { 
       if (arg2 != null) 
       { 
        System.out.println("Selected Group: " + arg1.getGroupId() + " - " + arg2.getGroupName()); 
       } 
      } 
     }); 

     final StackPane layout = new StackPane(); 
     layout.getChildren().add(listGroups); 
     layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;"); 
     stage.setScene(new Scene(layout)); 
     stage.show(); 
    } 

    class GroupListCell extends ListCell<ListGroupsObj> 
    { 
     @Override 
     protected void updateItem(ListGroupsObj item, boolean empty) 
     { 
      super.updateItem(item, empty); 
      if (item != null) 
      { 
       setText(item.getGroupId() + " - " + item.getGroupName()); 
      } 
     } 
    } 

    private List<ListGroupsObj> listGroups; 

    public static class ListGroupsObj 
    { 

     private int groupId; 
     private String groupName; 

     public static ListGroupsObj newInstance() 
     { 
      return new ListGroupsObj(); 
     } 

     public ListGroupsObj() 
     { 
     } 

     public ListGroupsObj groupId(int groupId) 
     { 
      this.groupId = groupId; 
      return this; 
     } 

     public ListGroupsObj groupName(String groupName) 
     { 
      this.groupName = groupName; 
      return this; 
     } 

     public int getGroupId() 
     { 
      return groupId; 
     } 

     public String getGroupName() 
     { 
      return groupName; 
     } 

     @Override 
     public String toString() 
     { 
      return groupId + " - " + groupName; 
     } 
    } 

    public class GroupConverter extends StringConverter<ListGroupsObj> 
    { 

     @Override 
     public String toString(ListGroupsObj obj) 
     { 
      return obj.getGroupId() + " - " + obj.getGroupName(); 
     } 

     @Override 
     public ListGroupsObj fromString(String obj) 
     { 

      //TODO when you type for example "45 - NextGroup" you want to take only tyhe number" 
      return ListGroupsObj.newInstance().groupName(obj); 
     } 

    } 
} 

我得到这个错误,当我点击下拉框中之外:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to com.selectmenuexample.MainApp$ListGroupsObj 

我发现这可以使用转换器完成,但我现在知道如何使用它。你能帮助这个实现吗?

+0

'listGroups.setConverter ..............'看起来像你应该设置你的自定义字符串转换器在这一行。 – SimY4

回答

4

这里是什么是错的:

  • 你叫你的ComboBox listGroups和你的项目listGroups的名单。所以在你的开始代码中,你隐藏了这个变量。所以我删除了这个无用的变量,因为你可以直接在ComboBox中操作Items。
  • 你基本上有三个方法/变量做同样的事情。将对象转换为一个字符串,并在它们之间使用“-”。所以我删除了GroupConverter和定制cellFactory。你不需要它们,因为你的ListGroupsObj中已经有了你的“toString()”方法。

然后你误解了ComboBox是如何工作的。如果它是可编辑的,那么ComboBox将允许在TextField内键入内容。这就是StringConverter来的地方。它将允许您在String和ListGroupsObj之间进行转换。

为了从ListGroupsObj转到字符串,只需在对象上调用“toString()”方法即可。

但是在这种情况下,您应该创建一个新的ListGroupsObj,或者验证组合框内的内容不是您的一个项目。例如,如果您在组合框中选择一个项目,则将调用来自String()的。但是你不想创建一个新的ListGroupsObj,你只想在你的项目List中隔离ListGroupsObj并返回它。

现在,您可以保证在ComboBox上调用getValue()将始终返回ListGroupsObj对象,因为您提供了自定义的有效StringConverter。

这里是你的代码的简化和工作版本:

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import javafx.util.StringConverter; 

public class MainApp extends Application { 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 

     final ComboBox<ListGroupsObj> comboBox = new ComboBox(); 

     comboBox.setEditable(true); 
     comboBox.setConverter(new StringConverter<ListGroupsObj>() { 

      @Override 
      public String toString(ListGroupsObj obj) { 
       return obj.toString(); 
      } 

      @Override 
      public ListGroupsObj fromString(String obj) { 
       //Here we try to identify if the given String actually represents one item of our list 
       for(ListGroupsObj tempObj:comboBox.getItems()){ 
        if(tempObj.toString().equals(obj)){ 
         return tempObj; 
        } 
       } 
       //If not we just create a new one 
       return ListGroupsObj.newInstance().groupName(obj); 
      } 
     }); 

     // Insert Some data 
     ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Test"); 
     comboBox.getItems().addAll(ob); 
     ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Test2"); 
     comboBox.getItems().addAll(osb); 
     comboBox.setValue(ob); 

     final StackPane layout = new StackPane(); 
     layout.getChildren().add(comboBox); 
     layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;"); 
     stage.setScene(new Scene(layout)); 
     stage.show(); 
    } 

    public static class ListGroupsObj { 

     private int groupId; 
     private String groupName; 

     public static ListGroupsObj newInstance() { 
      return new ListGroupsObj(); 
     } 

     public ListGroupsObj() { 
     } 

     public ListGroupsObj groupId(int groupId) { 
      this.groupId = groupId; 
      return this; 
     } 

     public ListGroupsObj groupName(String groupName) { 
      this.groupName = groupName; 
      return this; 
     } 

     public int getGroupId() { 
      return groupId; 
     } 

     public String getGroupName() { 
      return groupName; 
     } 

     @Override 
     public String toString() { 
      return groupId + " - " + groupName; 
     } 
    } 
} 

PS:这个问题在官方的JavaFX问题跟踪已经长大,我会离开这里的链接,因为在另一例票(需要登录):https://javafx-jira.kenai.com/browse/RT-29118