首页 > 解决方案 > 由于绑定而加载 FXML 时出现 IndexOutOfBoundsException

问题描述

我正在构建一个 JavaFX 应用程序,并且正在使用 bingings。一切正常,但这一行引发异常。

ExportarControlador.class

//List of loaded images, it contains information to find the real image file
private ObservableList<ImgBean> list;

//Indicator to mark which image from the list should be displayed now
private SimpleIntegerProperty indicator;

@FXML private ImageView imageView;

//...

@Override
public void initialize(URL arg0, ResourceBundle arg1){

    //...   

    imageView.imageProperty().bind(Bindings.when(
                Bindings.isEmpty(list))
                .then(new SimpleObjectProperty<ImgBean>())
                .otherwise(new SimpleObjectProperty<ImgBean>(new Image(someUtils.getURLFromImgBean(list.get(indicator.get()))))));

    //...
}

这背后的想法是绑定应该检查ObservableList. 当列表为空时,不ImageView显示图像。当列表有图像时,ImageView应该显示图像list.get(indicator)。指标永远不能是< 0or >= list.size(),我已经检查过了。这是堆栈跟踪。

javafx.fxml.LoadException: 
/C:/Users/[path-to-my-project]/exportar.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601) ~[jfxrt.jar:?]
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579) ~[jfxrt.jar:?]
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441) ~[jfxrt.jar:?]
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409) ~[jfxrt.jar:?]
    at com.bcadaval.memefinder3020.principal.SpringFxmlLoader.cargaVistas(SpringFxmlLoader.java:50) ~[classes/:?]
    at com.bcadaval.memefinder3020.concurrencia.TaskSplash.call(TaskSplash.java:68) ~[classes/:?]
    at com.bcadaval.memefinder3020.concurrencia.TaskSplash.call(TaskSplash.java:1) ~[classes/:?]
    at javafx.concurrent.Task$TaskCallable.call(Task.java:1423) ~[jfxrt.jar:?]
    at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_221]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_221]
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(Unknown Source) ~[?:1.8.0_221]
    at java.util.ArrayList.get(Unknown Source) ~[?:1.8.0_221]
    at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89) ~[jfxrt.jar:?]
    at com.bcadaval.memefinder3020.controlador.ExportarControlador.initialize(ExportarControlador.java:156) ~[classes/:?]
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548) ~[jfxrt.jar:?]
    ... 8 more

显然异常的原因是,不知何故,.otherwise()被调用,但它没有任何意义,因为列表总是空的,除非我点击一个填充它的按钮,所以.then()应该是唯一调用的方法。

我没有.otherwise()正确绑定吗?我是否错过了任何其他方法来实现更简单的相同结果?谢谢。

标签: javajavafxbinding

解决方案


fluent API 不作为Bindings.when(...)快捷操作符:换句话说,otherwise()即使子句中的条件when()为真,它也会评估子句(相反,then()即使when()子句为假,也会评估子句)。

相反,您可以直接创建自定义绑定:

imageView.imageProperty().bind(Bindings.createObjectBinding(() -> {
    if (list.isEmpty()) {
        return null ;
    } else {
        int index = indicator.get();
        ImgBean imgBean = list.get(index);
        URL imageUrl = someUtils.getURLFromImgBean(imgBean);
        return new Image(imageUrl);
    }
}, list, indicator);

如果需要,您也可以相当容易地使用它来检查索引是否在界限内。


推荐阅读