如何将空项正确添加到JavaFX';组合框

如何将空项正确添加到JavaFX';组合框,java,javafx-8,Java,Javafx 8,如何将null项正确添加到JavaFX的组合框 我试过这个: @FXML private ComboBox<Producto> comboProductos; private ObservableList<Producto> productos; productos = FXCollections.observableArrayList(ProductoDAO.obtenerProductos()); productos.add(0, null); comboPro

如何将
null
项正确添加到JavaFX的
组合框

我试过这个:

@FXML 
private ComboBox<Producto> comboProductos;
private ObservableList<Producto> productos;

productos = FXCollections.observableArrayList(ProductoDAO.obtenerProductos());
productos.add(0, null);
comboProductos.setItems(productos);

您可以创建一个包含
Producto
类型元素的
ComboBoxItem
-类。 这样,您可以将包含的元素设置为null,但仍然在
toString()
-方法中返回字符串。
然后,Combox将包含ComboxItems而不是产品

下面是一个示例代码,它将
null
添加到
组合框
。代码运行时没有任何运行时错误:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.geometry.Pos;
import javafx.collections.*;
public class FxComboBox extends Application {
    public static void main(String [] args) {
        launch(args);
    }
    @Override
    public void start(Stage primaryStage) {
        ObservableList<Product> products = FXCollections.observableArrayList(
                                                new Product(1, "Books"),
                                                new Product(2, "Pencils"),
                                                new Product(3, "Folders"),
                                                new Product(9, "Paper Clips"));
        products.add(0, null);
        ComboBox<Product> productsCombo = new ComboBox<>();
        productsCombo.setItems(products);
        HBox hbox = new HBox();
        hbox.setAlignment(Pos.CENTER);
        hbox.getChildren().add(productsCombo);
        Scene scene = new Scene(hbox, 400, 200);
        primaryStage.setTitle("Combo Box Demo");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
class Product {
    private int id;
    private String name;
    public Product(int id, String name) {
        this.name = name;
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return Integer.toString(id) + " " + name;
    }
}
示例代码反映了这一点:

更改此项:

致:


这是一个适用于您想要使用的任何自定义对象的工作解决方案

首先创建名为GenericCallback的类:

import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;

public abstract class GenericCallback<T> implements Callback<ListView<Object>, ListCell<Object>> {
    @Override
    public ListCell<Object> call(ListView<Object> param) {
        final ListCell<Object> cell = new ListCell<Object>() {
            @Override
            protected void updateItem(Object t, boolean empty) {
                super.updateItem(t, empty);
                try {
                    if (t instanceof String) {
                        setText((String)t);
                    } else {
                        //hopefully it is generic
                        T abc = (T)t;
                        setText(toText(abc));
                    }
                } catch (Exception e) {
                    //oh well, looks like it was not.
                    setText("");
                }
        };
        return cell;
    }

    public abstract String toText(T object);
}

没有运行时错误,因为您没有向combobox添加null对象。使用新的组合框,您只需替换泛型类型User,然后处理另一个对象。我希望它能有所帮助。

行号:MainApp.java:273I的代码是什么?我更正了它,它不是NullPointerException,它是IndexOutOfBoundsException。这和我现在做的一样,并且仍然抛出IndexOutOfBoundsException。告诉我您希望在组合框中使用空乘积的原因是什么?我已经在答案中添加了一个解决方案。请参阅更新。
public String toString() {
    if ((id == -1) && (name.isEmpty())) {
        return "";
    }
    else {
        return Integer.toString(id) + " " + name;
    }
}
products.add(0, null);
Product dummy = new Product(-1, "");
products.add(0, dummy);
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;

public abstract class GenericCallback<T> implements Callback<ListView<Object>, ListCell<Object>> {
    @Override
    public ListCell<Object> call(ListView<Object> param) {
        final ListCell<Object> cell = new ListCell<Object>() {
            @Override
            protected void updateItem(Object t, boolean empty) {
                super.updateItem(t, empty);
                try {
                    if (t instanceof String) {
                        setText((String)t);
                    } else {
                        //hopefully it is generic
                        T abc = (T)t;
                        setText(toText(abc));
                    }
                } catch (Exception e) {
                    //oh well, looks like it was not.
                    setText("");
                }
        };
        return cell;
    }

    public abstract String toText(T object);
}
GenericCallback gc = new GenericCallback<User>() {
    @Override
    public String toText(User user) {
        return FormattingUtil.getUserName(user);
    }
};
ComboBox comboboxUser = new Combobox();
comboboxUser.setButtonCell(gc.call(null));
comboboxUser.setCellFactory(gc);
comboboxUser.setOnAction(new EventHandler<ActionEvent>() {
   @Override
   public void handle(ActionEvent event) {
        Object selectedItem = comboboxIzd.getSelectionModel().getSelectedItem();
        if (selectedItem instanceof User) {
            User thisUserIsSelected = (User) selectedItem;
            //do whatever you wish with it
        } else {
            //empty item was selected - no user was selected, do whatever you wish with it
        }
    }
});
comboboxUser.getItems().add("");//add empty string for example
comboboxIzd.getItems().add("no selection but still some text");
comboboxUser.getItems().addAll(listOfSomeUserObjects);
comboboxIzd.getItems().add("no selection at the end ...");