我想包括对我的组合框的检查,以限制对某些值的“访问”.我可以从列表中删除那些无法访问的项目,是的,但是我希望用户看到其他选项,即使他还不能选择它们.
问题:在changelistener中选择另一个值会导致IndexOutOfBoundsException,我不知道为什么.
这是一个SSCCE.它创建一个带有整数值的ComboBox,默认情况下会选择第一个.然后我试着保持它很容易:每次更改值都被视为“错误”,我将选择更改回第一个元素.但仍然是,IndexOutOfBounds:
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.ComboBox; import javafx.stage.Stage; public class Tester extends Application{ public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { ComboBox<Integer> box = new ComboBox<Integer>(); ObservableList<Integer> vals= FXCollections.observableArrayList(0,1,2,3); box.setItems(vals); box.getSelectionModel().select(0); /*box.valueProperty().addListener((observable, oldValue, newValue) -> { box.getSelectionModel().select(0); });*/ /*box.getSelectionModel().selectedItemProperty().addListener((observable,oldValue,newValue)->{ System.out.println(oldValue+","+newValue); box.getSelectionModel().select(0); });*/ box.getSelectionModel().selectedIndexProperty().addListener((observable,oldValue,newValue)->{ System.out.println(oldValue+","+newValue); box.getSelectionModel().select(0); }); Scene scene = new Scene(new Group(box),500,500); stage.setScene(scene); stage.show(); } }
我用valueProperty,selectedItemProperty和selectedIndexProperty测试了它,以及所有这些:
box.getSelectionModel().select(0); box.getSelectionModel().selectFirst(); box.getSelectionModel().selectPrevious(); box.setValue(0); if (oldValue.intValue() < newValue.intValue()) box.getSelectionModel().select(oldValue.intValue());
唯一有效的想法是设定价值本身:
box.getSelectionModel().select(box.getSelectionModel().getSelectedIndex()); box.setValue(box.getValue));
这是例外:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(Unknown Source) at javafx.collections.ListChangeListener$Change.getAddedSubList(Unknown Source) at com.sun.javafx.scene.control.behavior.ListViewBehavior.lambda$new$178(Unknown Source) at com.sun.javafx.scene.control.behavior.ListViewBehavior$$Lambda$126/644961012.onChanged(Unknown Source) at javafx.collections.WeakListChangeListener.onChanged(Unknown Source) at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(Unknown Source) at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(Unknown Source) at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(Unknown Source) at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(Unknown Source) at javafx.scene.control.ListView$ListViewBitSetSelectionModel.clearAndSelect(Unknown Source) at com.sun.javafx.scene.control.behavior.CellBehaviorBase.simpleSelect(Unknown Source) at com.sun.javafx.scene.control.behavior.CellBehaviorBase.doSelect(Unknown Source) at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(Unknown Source) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source) at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source) at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source) at javafx.event.Event.fireEvent(Unknown Source) at javafx.scene.Scene$MouseHandler.process(Unknown Source) at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source) at javafx.scene.Scene.impl_processMouseEvent(Unknown Source) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$172/2037973250.get(Unknown Source) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source) at com.sun.glass.ui.View.handleMouseEvent(Unknown Source) at com.sun.glass.ui.View.notifyMouse(Unknown Source) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source) at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
我究竟做错了什么?
在JavaFX中,当更改已在进行中时,您无法更改ObservableList的内容.这里发生的是你的侦听器(你试过的任何一个)被作为box.getSelctionModel()的一部分被触发.getSelectedItems()ObservableList更改.所以基本上,在处理选择更改时,您无法更改选择.
无论如何,你的解决方案有点笨拙.如果您在所选项目(或组合框值)上有另一个侦听器,即使您的方法有效,它也会暂时看到具有“非法”选择的组合框.例如,在上面的例子中,如果用户试图选择“1”,则另一个听众会看到选择改变为不允许的值“1”,然后返回到“0”.处理此监听器中不应允许的值可能会使您的程序逻辑变得非常复杂.
更好的方法是阻止用户选择不允许的值.您可以使用设置单元格的禁用属性的单元工厂执行此操作:
box.setCellFactory(lv -> new ListCell<Integer>() { @Override public void updateItem(Integer item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); } else { setText(item.toString()); setDisable(item.intValue() != 0); } } });
在外部样式表中包含以下内容将为用户提供通常的视觉提示:项目不可选:
.combo-box-popup .list-cell:disabled { -fx-opacity: 0.4 ; }
翻译自:https://stackoverflow.com/questions/32370394/javafx-combobox-change-value-causes-indexoutofboundsexception