如何将null
项目正确添加到JavaFX的ComboBox<T>
?
我已经尝试过了:
@FXML
private ComboBox<Producto> comboProductos;
private ObservableList<Producto> productos;
productos = FXCollections.observableArrayList(ProductoDAO.obtenerProductos());
productos.add(0, null);
comboProductos.setItems(productos);
它可以工作,但是在选择null
项时会抛出此异常:
java.lang.IndexOutOfBoundsException: null
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136) ~[jfxrt.jar:?]
at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:242) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.behavior.ListViewBehavior.lambda$new$177(ListViewBehavior.java:269) ~[jfxrt.jar:?]
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88) ~[jfxrt.jar:?]
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329) ~[jfxrt.jar:?]
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75) ~[jfxrt.jar:?]
at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(MultipleSelectionModelBase.java:378) ~[jfxrt.jar:?]
at javafx.scene.control.ListView$ListViewBitSetSelectionModel.clearAndSelect(ListView.java:1403) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.simpleSelect(CellBehaviorBase.java:256) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.doSelect(CellBehaviorBase.java:220) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:150) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95) ~[jfxrt.jar:?]
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) ~[jfxrt.jar:?]
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) ~[jfxrt.jar:?]
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) ~[jfxrt.jar:?]
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) ~[jfxrt.jar:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) ~[jfxrt.jar:?]
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) ~[jfxrt.jar:?]
at javafx.event.Event.fireEvent(Event.java:198) ~[jfxrt.jar:?]
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) ~[jfxrt.jar:?]
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) ~[jfxrt.jar:?]
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) ~[jfxrt.jar:?]
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) ~[jfxrt.jar:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394) ~[jfxrt.jar:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) ~[jfxrt.jar:?]
at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_172]
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432) ~[jfxrt.jar:?]
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) ~[jfxrt.jar:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431) ~[jfxrt.jar:?]
at com.sun.glass.ui.View.handleMouseEvent(View.java:555) ~[jfxrt.jar:?]
at com.sun.glass.ui.View.notifyMouse(View.java:937) ~[jfxrt.jar:?]
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) ~[jfxrt.jar:?]
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177) ~[jfxrt.jar:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_172]
答案 0 :(得分:1)
下面是一个示例代码,它向null
添加了ComboBox
。该代码运行时没有任何运行时错误:
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;
}
}
更新:
以下是解决方法:
创建一个名为{em> dummy 的Product
。这将具有id = -1(或在实际应用中未使用的东西)和name =“”(空字符串)。 Product
类的重写toString
方法可能会考虑使用此 dummy 产品并返回一个空字符串:
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);
答案 1 :(得分:0)
您可以创建一个ComboBoxItem<T>
类,其中包含一个Producto
类型的Element。
这样,您可以将所包含的元素设置为null,但仍可以在toString()
方法中返回一个String。
然后,Combox将包含ComboxItems而不是Products。
答案 2 :(得分:0)
这是适用于您要使用的任何自定义对象的解决方案。
首先创建一个名为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);
}
然后您可以像这样实现它:
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 ...");
没有运行时错误,因为您没有将空对象添加到组合框。使用新的组合框,您只需替换通用类型User,即可处理另一个对象。希望对您有所帮助。